From 290ae745b0537c7c8fd1635c7b1b8172c7e0afe2 Mon Sep 17 00:00:00 2001 From: "Zhuk, Alexander" Date: Thu, 3 Mar 2016 14:27:41 +0300 Subject: [PATCH 01/53] multiple grids example texts --- README.md | 12 ++---------- demo/bootstrap/multiple.html | 3 ++- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 91cdfae..39290e2 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Demo 100k: http://angular-data-grid.github.io/demo/100k/ - Easily switch between the most popular Bootstrap and Google Material theming, or apply your own CSS theme just by changing several CSS classes. - Built-in sync with browser address bar (URL), so you can copy-n-paste sorting/filtering/pagination results URL and open it in other browser / send to anyone - even if pagination / filtering are done on a client-side. - Unlike most part of other Angular DataGrids, we intentionally use non-isolated scope of the directive to maximize flexibility, so it can be easily synchronized with any data changes inside your controller. - NOTE! With great power comes great responsibility, so use non-isolated API carefully. + NOTE! With great power comes great responsibility, so use non-isolated API wisely. ### Installation @@ -80,14 +80,6 @@ angular.module('myApp', ['dataGrid', 'pagination']) sort: { predicate: 'companyName', direction: 'asc' - }, - //optional parameter - custom rules for filters (see explanation below) - customFilters: { - startFrom: function (items, value, predicate) { - return items.filter(function (item) { - return value && item[predicate] ? !item[predicate].toLowerCase().indexOf(value.toLowerCase()) : true; - }); - } } }; ``` @@ -234,4 +226,4 @@ Then create in `gridOptions.customFilters` variable named as `ng-model` with fil ### Others All filters have optional parameter `disable-url`. If you set it to **true**, URL-synchronization for this filter will be disabled. -If you need to use 2 or more grids on page, please add id to grids, and then use ```grid-id``` attribute on filters to specify their corresponding grid. +If you need to use 2 or more grids on page, please add id to grids, and then use ```grid-id``` attribute on filters to specify their corresponding grid. [example](http://angular-data-grid.github.io/demo/bootstrap/multiple.html) diff --git a/demo/bootstrap/multiple.html b/demo/bootstrap/multiple.html index a1bcaf7..35f4cce 100644 --- a/demo/bootstrap/multiple.html +++ b/demo/bootstrap/multiple.html @@ -20,7 +20,8 @@

Angular Data Grid - Multiple Grids Example

- Do not forget to assign id attribute for each grid instance on a page to make them work simultaneously. Otherwise grids will share sorting and filtering actions.
+ You need to assign id attribute for each grid instance on a page to make them work simultaneously. If you use external filtering, assign grid-id to id and ng-change to associated + gridActions (see example below). Project GitHub

From b7313b6295b3cc8e7600c539f8e9aed97631509c Mon Sep 17 00:00:00 2001 From: "Zhuk, Alexander" Date: Thu, 3 Mar 2016 15:46:52 +0300 Subject: [PATCH 02/53] adding NOTE about 'grid-item' wrapper directive --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 39290e2..29239c1 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,8 @@ angular.module('myApp', ['dataGrid', 'pagination']) }; ``` +NOTE: `grid-item` wrapper used in the code example above, to make code more concise - you can use regular 'ng-repeat' instead if needed. + ### Basic API 1. `grid-options`: object in your controller with start options for grid. You must create this object with at least 1 required parameter - data. From ab1d19e9e6bf349b866174177cf841598a03b8c2 Mon Sep 17 00:00:00 2001 From: "Zhuk, Alexander" Date: Thu, 3 Mar 2016 15:48:02 +0300 Subject: [PATCH 03/53] adding NOTE about 'grid-item' wrapper directive2 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 29239c1..0216edd 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ angular.module('myApp', ['dataGrid', 'pagination']) }; ``` -NOTE: `grid-item` wrapper used in the code example above, to make code more concise - you can use regular 'ng-repeat' instead if needed. +NOTE: `grid-item` wrapper directive used in the example above, to make code more concise - you can use regular `ng-repeat` instead if needed. ### Basic API From 76cf3fbc2f1d00819a95640d5a4586312e74ff82 Mon Sep 17 00:00:00 2001 From: "Zhuk, Alexander" Date: Thu, 3 Mar 2016 16:39:12 +0300 Subject: [PATCH 04/53] adding NPM INSTALL support and updated descriptions --- README.md | 12 ++++++------ demo/bootstrap/multiple.html | 2 +- package.json | 28 ++++++++++++++++++++++++++-- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 0216edd..6eaf9a7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ##Angular Data Grid Light, flexible and performant Data Grid for AngularJS apps, with built-in sorting, pagination and filtering options, unified API for client-side and server-side data fetching, -seamless synchronization with browser address bar and total freedom in mark-up and styling suitable for your application. +seamless synchronization with browser address bar and total freedom in mark-up and styling suitable for your application. Angular 1.3 - 1.5 compliant. Demo Bootstrap: http://angular-data-grid.github.io/demo/bootstrap/ @@ -156,7 +156,7 @@ Directive is built on a base of excellent [Angular UI](https://angular-ui.github ``` -Settings can be provided as attributes in the or globally configured through the paginationConfig. +Settings can be provided as attributes in the or globally configured through the `paginationConfig`. ```ng-change``` : ng-change can be used together with ng-model to call a function whenever the page changes. @@ -190,8 +190,8 @@ Settings can be provided as attributes in the or globally configure ### Filters Data Grid supports 4 built-in types of filters: `text`, `select`, `dateFrom` and `dateTo`. -To use it, add attribute `filter-by` to any element and pass property name, which you want filtering. -Also you need add attribute `filter-type` with type of filter. +To use it, add attribute `filter-by` to any element and pass property name, which you want to be filtered. +Also you need add attribute `filter-type` with type of filter. After that you need call `filter()` method in `ng-change` for text or select inputs and in `ng-blur/ng-focus` for datepickers. Filters are synchronized with URL by `ng-model` value. @@ -207,7 +207,7 @@ Filters are synchronized with URL by `ng-model` value. ``` ### Custom Filters -If you need use some custom filters (f.e. filter by first letter), add `filter-by` to specify property name, which you want filtering and add `ng-model` property. +If you need to use some custom filters (e.g. filter by first letter), add `filter-by` to specify property name, which you want filtering and add `ng-model` property. Then create in `gridOptions.customFilters` variable named as `ng-model` with filtering function. Filtering function accepts items, value, predicate arguments and returns filtered array. ```javascript @@ -228,4 +228,4 @@ Then create in `gridOptions.customFilters` variable named as `ng-model` with fil ### Others All filters have optional parameter `disable-url`. If you set it to **true**, URL-synchronization for this filter will be disabled. -If you need to use 2 or more grids on page, please add id to grids, and then use ```grid-id``` attribute on filters to specify their corresponding grid. [example](http://angular-data-grid.github.io/demo/bootstrap/multiple.html) +If you need to use 2 or more grids on page, please add `id` to grids, and then use `grid-id` attribute on filters to specify their corresponding grid. [Example](http://angular-data-grid.github.io/demo/bootstrap/multiple.html) diff --git a/demo/bootstrap/multiple.html b/demo/bootstrap/multiple.html index 35f4cce..d313957 100644 --- a/demo/bootstrap/multiple.html +++ b/demo/bootstrap/multiple.html @@ -20,7 +20,7 @@

Angular Data Grid - Multiple Grids Example

- You need to assign id attribute for each grid instance on a page to make them work simultaneously. If you use external filtering, assign grid-id to id and ng-change to associated + You need to assign id attribute for each grid instance on a page to make them work simultaneously. If you use external filtering, assign grid-id to grid id and ng-change to associated gridActions (see example below). Project GitHub
diff --git a/package.json b/package.json index e91cc83..3e5963a 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "data-grid", + "name": "angular-data-grid", "version": "0.1.0", "scripts": { "start": "gulp serve", @@ -13,5 +13,29 @@ "gulp-rimraf": "*", "gulp-sass": "^2.1.0", "gulp-uglify": "^1.4.2" - } + }, + "description": "Light, flexible and performant Data Grid for AngularJS apps, with built-in sorting, pagination and filtering options, unified API for client-side and server-side data fetching, \r seamless synchronization with browser address bar and total freedom in mark-up and styling suitable for your application. Angular 1.3 - 1.5 compliant.", + "main": "index.html", + "devDependencies": {}, + "repository": { + "type": "git", + "url": "git+https://github.com/angular-data-grid/angular-data-grid.github.io.git" + }, + "keywords": [ + "angular data grid", + "data grid", + "data grid for angular", + "ng-data-grid", + "ng-table", + "angular table", + "bootstra data grid", + "material design grid", + "data table" + ], + "author": "Alexander Zhuk (https://github.com/angular-data-grid/angular-data-grid.github.io)", + "license": "ISC", + "bugs": { + "url": "https://github.com/angular-data-grid/angular-data-grid.github.io/issues" + }, + "homepage": "https://github.com/angular-data-grid/angular-data-grid.github.io#readme" } From 425c63ce2c6511dd71a7bfa0627cd0ccfe6b5e11 Mon Sep 17 00:00:00 2001 From: AlexZ Date: Thu, 3 Mar 2016 16:40:18 +0300 Subject: [PATCH 05/53] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 6eaf9a7..8baf5fe 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ Demo 100k: http://angular-data-grid.github.io/demo/100k/ Using Bower: `bower install angular-data-grid` +Using NPM: `npm install angular-data-grid` + Direct download: get ZIP archive [from here](https://github.com/angular-data-grid/angular-data-grid.github.io/archive/master.zip) Then use files from *dist* folder (see below). From 7d8ec4ae9c42d77f32154820a0b77dc1995d7e27 Mon Sep 17 00:00:00 2001 From: "Zhuk, Alexander" Date: Tue, 26 Apr 2016 13:23:57 +0300 Subject: [PATCH 06/53] fixing Angular Material select filter issue --- dist/dataGrid.js | 6 ++++-- dist/dataGrid.min.js | 2 +- src/js/dataGrid.js | 2 -- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dist/dataGrid.js b/dist/dataGrid.js index 94666e8..7586454 100644 --- a/dist/dataGrid.js +++ b/dist/dataGrid.js @@ -276,6 +276,8 @@ .directive('gridData', ['$compile', '$animate', function ($compile) { return { restrict: 'EA', + //transclude: true, + //replace: true, scope: true, controller: 'gridController', link: function ($scope, $element, attrs) { @@ -319,11 +321,13 @@ && !element.attr('ng-blur')) { element.attr('ng-focus', "filter('{" + urlName + " : " + "this." + urlName + "}')"); element.attr('ng-blur', "filter('{" + urlName + " : " + "this." + urlName + "}')"); + //$compile(element)($scope); } if (!urlName) { urlName = predicate; element.attr('ng-model', predicate); element.attr('ng-change', 'filter()'); + //$compile(element)($scope); } filters.push({ @@ -333,8 +337,6 @@ filterType: filterType, disableUrl: disableUrl }); - - $compile(element)($scope); }); angular.forEach(angular.element(directiveElement[0].querySelectorAll('[grid-item]')), function (row) { diff --git a/dist/dataGrid.min.js b/dist/dataGrid.min.js index f745d92..b6d1420 100644 --- a/dist/dataGrid.min.js +++ b/dist/dataGrid.min.js @@ -1 +1 @@ -!function(){"use strict";function t(t,e){var i=[];return t?(t.forEach(function(t){~i.indexOf(t[e])||i.push(t[e])}),i.map(function(t){return{text:t,value:t}})):void 0}angular.module("dataGrid",[]).filter("startFrom",function(){return function(t,e){return t?(e=+e,t.slice(e)):[]}}).controller("gridController",["$scope","$element","$filter","$location","filtersFactory",function(e,i,r,n,a){function o(){var t,i=!1;t="page="+e.paginationOptions.currentPage,e.paginationOptions.itemsPerPage!==e.defaultsPaginationOptions.itemsPerPage&&(t+="&itemsPerPage="+e.paginationOptions.itemsPerPage),e.sortOptions.predicate&&(t+="&sort="+encodeURIComponent(e.sortOptions.predicate+"-"+e.sortOptions.direction)),e.filters.forEach(function(r){var n=r.model,a=e.$eval(n);if(r.disableUrl)return void(i=!0);if(a){var o;if(a instanceof Date){if(isNaN(a.getTime()))return;o=a.getFullYear()+"-",o+=a.getMonth()<9?"0"+(a.getMonth()+1)+"-":a.getMonth()+1+"-",o+=a.getDate()<10?"0"+a.getDate():a.getDate(),a=o}t+="&"+encodeURIComponent(n)+"="+encodeURIComponent(a)}}),i&&c(),n.path(t)}function s(){var t=n.path().slice(1),i={},r={};if(e.params=i,t.split("&").forEach(function(t){var e=t.split("=");i[e[0]]=e[1],"page"!==e[0]&&"sort"!==e[0]&&"itemsPerPage"!==e[0]&&(r[decodeURIComponent(e[0])]=decodeURIComponent(e[1]))}),e.filters.forEach(function(t){var i=t.model,n=r[i];if(!t.disableUrl){if(~t.filterType.toLowerCase().indexOf("date"))return e.$parent.__evaltmp=n?new Date(n):null,void e.$parent.$eval(i+"=__evaltmp");"select"!==t.filterType||n||(n=""),n&&(e.__evaltmp=n,e.$eval(i+"=__evaltmp"))}}),e.serverPagination||p(),e.paginationOptions.itemsPerPage=e.defaultsPaginationOptions.itemsPerPage,e.paginationOptions.currentPage=e.defaultsPaginationOptions.currentPage,i.itemsPerPage&&(e.paginationOptions.itemsPerPage=i.itemsPerPage),i.page&&(!e.serverPagination&&(i.page-1)*e.paginationOptions.itemsPerPage>e.filtered.length?e.paginationOptions.currentPage=1:e.paginationOptions.currentPage=i.page),i.sort){var a=i.sort.split("-");e.sortOptions.predicate=decodeURIComponent(a[0]),e.sortOptions.direction=decodeURIComponent(a[1])}e.serverPagination||c()}function l(){var t=n.path().slice(1);e._gridOptions.getData("?"+t,function(t,i){e.filtered=t,e.paginationOptions.totalItems=i})}function c(){var t=Date.now(),i=!1;e._time={},e.sortOptions.predicate&&e.sortCache&&e.sortCache.predicate===e.sortOptions.predicate&&e.sortCache.direction===e.sortOptions.direction?(e.filtered=e.sortCache.data.slice(),i=!0):e.filtered=e._gridOptions.data.slice(),e._time.copy=Date.now()-t;var n=Date.now();p(),e._time.filters=Date.now()-n;var a=Date.now();e.sortOptions.predicate&&!i&&(e.filtered=r("orderBy")(e.filtered,e.sortOptions.predicate,"desc"===e.sortOptions.direction),e.sortCache={data:e.filtered.slice(),predicate:e.sortOptions.predicate,direction:e.sortOptions.direction}),e._time.sort=Date.now()-a,e._time.all=Date.now()-t,e.paginationOptions.totalItems=e.filtered.length}function p(){e.filters.forEach(function(t){var i=t.filterBy,r=t.model,n=e.$eval(r),o=t.filterType;if(e.customFilters[r])e.filtered=e.customFilters[r](e.filtered,n,i);else if(n&&o){var s=a.getFilterByType(o);s&&(e.filtered=s(e.filtered,n,i))}})}e._gridOptions=e.$eval(i.attr("grid-options")),e._gridActions=e.$eval(i.attr("grid-actions")),e.serverPagination="true"===i.attr("server-pagination"),e.getDataDelay=i.attr("get-delay")||350,e._gridActions||(e.$parent.$eval(i.attr("grid-actions")+"= {}"),e._gridActions=e.$parent.$eval(i.attr("grid-actions"))),e._gridOptions.grid=e,e.filtered=e._gridOptions.data.slice(),e.paginationOptions=e._gridOptions.pagination?angular.copy(e._gridOptions.pagination):{},e.defaultsPaginationOptions={itemsPerPage:e.paginationOptions.itemsPerPage||"10",currentPage:e.paginationOptions.currentPage||1},e.paginationOptions=angular.copy(e.defaultsPaginationOptions),e.sortOptions=e._gridOptions.sort?angular.copy(e._gridOptions.sort):{},e.customFilters=e._gridOptions.customFilters?angular.copy(e._gridOptions.customFilters):{},e.urlSync=e._gridOptions.urlSync,e.$watch("_gridOptions.data",function(i){i&&i.length&&(e.sortCache={},e.filtered=e._gridOptions.data.slice(),e.filters.forEach(function(i){"select"===i.filterType&&(e[i.model+"Options"]=t(e.filtered,i.filterBy))}),e.urlSync?s(n.path()):c())}),e.sort=function(t){var i=e.sortOptions.predicate===t&&"desc"===e.sortOptions.direction?"asc":"desc";e.sortOptions.predicate=t,e.sortOptions.direction=i,e.paginationOptions.currentPage=1,e.reloadGrid()},e.filter=function(){e.paginationOptions.currentPage=1,e.reloadGrid()},e.$on("$locationChangeSuccess",function(){(e.urlSync||e.serverPagination)&&(e.serverPagination&&(clearTimeout(e.getDataTimeout),e.getDataTimeout=setTimeout(l,e.getDataDelay)),e.filtered&&s(n.path()))}),e.reloadGrid=function(){e.urlSync||e.serverPagination?o():c()},e._gridActions.refresh=e.reloadGrid,e._gridActions.filter=e.filter,e._gridActions.sort=e.sort}]).directive("gridData",["$compile","$animate",function(e){return{restrict:"EA",scope:!0,controller:"gridController",link:function(i,r,n){var a=[],o=[],s=[],l=r.parent(),c=n.id,p="true"===n.serverPagination;angular.forEach(angular.element(l[0].querySelectorAll("[sortable]")),function(t){var r=angular.element(t),n=r.attr("sortable");a.push(r),r.attr("ng-class","{'sort-ascent' : sortOptions.predicate ==='"+n+"' && sortOptions.direction === 'asc', 'sort-descent' : sortOptions.predicate === '"+n+"' && sortOptions.direction === 'desc'}"),r.attr("ng-click","sort('"+n+"')"),e(r)(i)}),angular.forEach(angular.element(document.querySelectorAll("[filter-by]")),function(n){var a=angular.element(n),s=l.find(a).length>0,p=a.attr("filter-by"),g=a.attr("filter-type")||"",d=a.attr("ng-model"),u=a.attr("disable-url");c&&a.attr("grid-id")&&c!=a.attr("grid-id")||("select"!==g||(i[d+"Options"]=t(i.$eval(r.attr("grid-options")+".data"),p)),!~g.indexOf("date")||a.attr("ng-focus")||a.attr("ng-blur")||(a.attr("ng-focus","filter('{"+d+" : this."+d+"}')"),a.attr("ng-blur","filter('{"+d+" : this."+d+"}')")),d||(d=p,a.attr("ng-model",p),a.attr("ng-change","filter()")),o.push({model:d,isInScope:s,filterBy:p,filterType:g,disableUrl:u}),e(a)(i))}),angular.forEach(angular.element(l[0].querySelectorAll("[grid-item]")),function(t){var r=angular.element(t);s.push(r),p?r.attr("ng-repeat","item in filtered"):r.attr("ng-repeat","item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage track by $index"),e(r)(i)}),i.sorting=a,i.rows=s,i.filters=o}}}]).factory("filtersFactory",function(){function t(t,e,i){return t.filter(function(t){return e&&t[i]?t[i]===e:!0})}function e(t,e,i){return t.filter(function(t){return e&&t[i]?~(t[i]+"").toLowerCase().indexOf((e+"").toLowerCase()):!0})}function i(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]<=e+86399999:!0})}function r(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]>=e:!0})}return{getFilterByType:function(n){switch(n){case"select":return t;case"text":return e;case"dateTo":return i;case"dateFrom":return r;default:return null}}}})}(); \ No newline at end of file +!function(){"use strict";function t(t,e){var i=[];return t?(t.forEach(function(t){~i.indexOf(t[e])||i.push(t[e])}),i.map(function(t){return{text:t,value:t}})):void 0}angular.module("dataGrid",[]).filter("startFrom",function(){return function(t,e){return t?(e=+e,t.slice(e)):[]}}).controller("gridController",["$scope","$element","$filter","$location","filtersFactory",function(e,i,r,n,a){function o(){var t,i=!1;t="page="+e.paginationOptions.currentPage,e.paginationOptions.itemsPerPage!==e.defaultsPaginationOptions.itemsPerPage&&(t+="&itemsPerPage="+e.paginationOptions.itemsPerPage),e.sortOptions.predicate&&(t+="&sort="+encodeURIComponent(e.sortOptions.predicate+"-"+e.sortOptions.direction)),e.filters.forEach(function(r){var n=r.model,a=e.$eval(n);if(r.disableUrl)return void(i=!0);if(a){var o;if(a instanceof Date){if(isNaN(a.getTime()))return;o=a.getFullYear()+"-",o+=a.getMonth()<9?"0"+(a.getMonth()+1)+"-":a.getMonth()+1+"-",o+=a.getDate()<10?"0"+a.getDate():a.getDate(),a=o}t+="&"+encodeURIComponent(n)+"="+encodeURIComponent(a)}}),i&&c(),n.path(t)}function s(){var t=n.path().slice(1),i={},r={};if(e.params=i,t.split("&").forEach(function(t){var e=t.split("=");i[e[0]]=e[1],"page"!==e[0]&&"sort"!==e[0]&&"itemsPerPage"!==e[0]&&(r[decodeURIComponent(e[0])]=decodeURIComponent(e[1]))}),e.filters.forEach(function(t){var i=t.model,n=r[i];if(!t.disableUrl){if(~t.filterType.toLowerCase().indexOf("date"))return e.$parent.__evaltmp=n?new Date(n):null,void e.$parent.$eval(i+"=__evaltmp");"select"!==t.filterType||n||(n=""),n&&(e.__evaltmp=n,e.$eval(i+"=__evaltmp"))}}),e.serverPagination||p(),e.paginationOptions.itemsPerPage=e.defaultsPaginationOptions.itemsPerPage,e.paginationOptions.currentPage=e.defaultsPaginationOptions.currentPage,i.itemsPerPage&&(e.paginationOptions.itemsPerPage=i.itemsPerPage),i.page&&(!e.serverPagination&&(i.page-1)*e.paginationOptions.itemsPerPage>e.filtered.length?e.paginationOptions.currentPage=1:e.paginationOptions.currentPage=i.page),i.sort){var a=i.sort.split("-");e.sortOptions.predicate=decodeURIComponent(a[0]),e.sortOptions.direction=decodeURIComponent(a[1])}e.serverPagination||c()}function l(){var t=n.path().slice(1);e._gridOptions.getData("?"+t,function(t,i){e.filtered=t,e.paginationOptions.totalItems=i})}function c(){var t=Date.now(),i=!1;e._time={},e.sortOptions.predicate&&e.sortCache&&e.sortCache.predicate===e.sortOptions.predicate&&e.sortCache.direction===e.sortOptions.direction?(e.filtered=e.sortCache.data.slice(),i=!0):e.filtered=e._gridOptions.data.slice(),e._time.copy=Date.now()-t;var n=Date.now();p(),e._time.filters=Date.now()-n;var a=Date.now();e.sortOptions.predicate&&!i&&(e.filtered=r("orderBy")(e.filtered,e.sortOptions.predicate,"desc"===e.sortOptions.direction),e.sortCache={data:e.filtered.slice(),predicate:e.sortOptions.predicate,direction:e.sortOptions.direction}),e._time.sort=Date.now()-a,e._time.all=Date.now()-t,e.paginationOptions.totalItems=e.filtered.length}function p(){e.filters.forEach(function(t){var i=t.filterBy,r=t.model,n=e.$eval(r),o=t.filterType;if(e.customFilters[r])e.filtered=e.customFilters[r](e.filtered,n,i);else if(n&&o){var s=a.getFilterByType(o);s&&(e.filtered=s(e.filtered,n,i))}})}e._gridOptions=e.$eval(i.attr("grid-options")),e._gridActions=e.$eval(i.attr("grid-actions")),e.serverPagination="true"===i.attr("server-pagination"),e.getDataDelay=i.attr("get-delay")||350,e._gridActions||(e.$parent.$eval(i.attr("grid-actions")+"= {}"),e._gridActions=e.$parent.$eval(i.attr("grid-actions"))),e._gridOptions.grid=e,e.filtered=e._gridOptions.data.slice(),e.paginationOptions=e._gridOptions.pagination?angular.copy(e._gridOptions.pagination):{},e.defaultsPaginationOptions={itemsPerPage:e.paginationOptions.itemsPerPage||"10",currentPage:e.paginationOptions.currentPage||1},e.paginationOptions=angular.copy(e.defaultsPaginationOptions),e.sortOptions=e._gridOptions.sort?angular.copy(e._gridOptions.sort):{},e.customFilters=e._gridOptions.customFilters?angular.copy(e._gridOptions.customFilters):{},e.urlSync=e._gridOptions.urlSync,e.$watch("_gridOptions.data",function(i){i&&i.length&&(e.sortCache={},e.filtered=e._gridOptions.data.slice(),e.filters.forEach(function(i){"select"===i.filterType&&(e[i.model+"Options"]=t(e.filtered,i.filterBy))}),e.urlSync?s(n.path()):c())}),e.sort=function(t){var i=e.sortOptions.predicate===t&&"desc"===e.sortOptions.direction?"asc":"desc";e.sortOptions.predicate=t,e.sortOptions.direction=i,e.paginationOptions.currentPage=1,e.reloadGrid()},e.filter=function(){e.paginationOptions.currentPage=1,e.reloadGrid()},e.$on("$locationChangeSuccess",function(){(e.urlSync||e.serverPagination)&&(e.serverPagination&&(clearTimeout(e.getDataTimeout),e.getDataTimeout=setTimeout(l,e.getDataDelay)),e.filtered&&s(n.path()))}),e.reloadGrid=function(){e.urlSync||e.serverPagination?o():c()},e._gridActions.refresh=e.reloadGrid,e._gridActions.filter=e.filter,e._gridActions.sort=e.sort}]).directive("gridData",["$compile","$animate",function(e){return{restrict:"EA",scope:!0,controller:"gridController",link:function(i,r,n){var a=[],o=[],s=[],l=r.parent(),c=n.id,p="true"===n.serverPagination;angular.forEach(angular.element(l[0].querySelectorAll("[sortable]")),function(t){var r=angular.element(t),n=r.attr("sortable");a.push(r),r.attr("ng-class","{'sort-ascent' : sortOptions.predicate ==='"+n+"' && sortOptions.direction === 'asc', 'sort-descent' : sortOptions.predicate === '"+n+"' && sortOptions.direction === 'desc'}"),r.attr("ng-click","sort('"+n+"')"),e(r)(i)}),angular.forEach(angular.element(document.querySelectorAll("[filter-by]")),function(e){var n=angular.element(e),a=l.find(n).length>0,s=n.attr("filter-by"),p=n.attr("filter-type")||"",g=n.attr("ng-model"),d=n.attr("disable-url");c&&n.attr("grid-id")&&c!=n.attr("grid-id")||("select"!==p||(i[g+"Options"]=t(i.$eval(r.attr("grid-options")+".data"),s)),!~p.indexOf("date")||n.attr("ng-focus")||n.attr("ng-blur")||(n.attr("ng-focus","filter('{"+g+" : this."+g+"}')"),n.attr("ng-blur","filter('{"+g+" : this."+g+"}')")),g||(g=s,n.attr("ng-model",s),n.attr("ng-change","filter()")),o.push({model:g,isInScope:a,filterBy:s,filterType:p,disableUrl:d}))}),angular.forEach(angular.element(l[0].querySelectorAll("[grid-item]")),function(t){var r=angular.element(t);s.push(r),p?r.attr("ng-repeat","item in filtered"):r.attr("ng-repeat","item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage track by $index"),e(r)(i)}),i.sorting=a,i.rows=s,i.filters=o}}}]).factory("filtersFactory",function(){function t(t,e,i){return t.filter(function(t){return e&&t[i]?t[i]===e:!0})}function e(t,e,i){return t.filter(function(t){return e&&t[i]?~(t[i]+"").toLowerCase().indexOf((e+"").toLowerCase()):!0})}function i(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]<=e+86399999:!0})}function r(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]>=e:!0})}return{getFilterByType:function(n){switch(n){case"select":return t;case"text":return e;case"dateTo":return i;case"dateFrom":return r;default:return null}}}})}(); \ No newline at end of file diff --git a/src/js/dataGrid.js b/src/js/dataGrid.js index 89bccc4..7586454 100644 --- a/src/js/dataGrid.js +++ b/src/js/dataGrid.js @@ -337,8 +337,6 @@ filterType: filterType, disableUrl: disableUrl }); - - $compile(element)($scope); }); angular.forEach(angular.element(directiveElement[0].querySelectorAll('[grid-item]')), function (row) { From dbb495ec28e33581d3146b5dfcf7c2d09898ce00 Mon Sep 17 00:00:00 2001 From: Igor Korshuk Date: Thu, 19 May 2016 16:13:04 +0300 Subject: [PATCH 07/53] #11 Text based filter does not filter out empty/null values --- dist/dataGrid.js | 2 +- dist/dataGrid.min.js | 2 +- src/js/dataGrid.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/dataGrid.js b/dist/dataGrid.js index 7586454..a5bdfeb 100644 --- a/dist/dataGrid.js +++ b/dist/dataGrid.js @@ -365,7 +365,7 @@ function textFilter(items, value, predicate) { return items.filter(function (item) { - return value && item[predicate] ? ~(item[predicate] + '').toLowerCase().indexOf((value + '').toLowerCase()) : true; + return value && item[predicate] ? ~(item[predicate] + '').toLowerCase().indexOf((value + '').toLowerCase()) : !!item[predicate]; }); } diff --git a/dist/dataGrid.min.js b/dist/dataGrid.min.js index b6d1420..e9c6a48 100644 --- a/dist/dataGrid.min.js +++ b/dist/dataGrid.min.js @@ -1 +1 @@ -!function(){"use strict";function t(t,e){var i=[];return t?(t.forEach(function(t){~i.indexOf(t[e])||i.push(t[e])}),i.map(function(t){return{text:t,value:t}})):void 0}angular.module("dataGrid",[]).filter("startFrom",function(){return function(t,e){return t?(e=+e,t.slice(e)):[]}}).controller("gridController",["$scope","$element","$filter","$location","filtersFactory",function(e,i,r,n,a){function o(){var t,i=!1;t="page="+e.paginationOptions.currentPage,e.paginationOptions.itemsPerPage!==e.defaultsPaginationOptions.itemsPerPage&&(t+="&itemsPerPage="+e.paginationOptions.itemsPerPage),e.sortOptions.predicate&&(t+="&sort="+encodeURIComponent(e.sortOptions.predicate+"-"+e.sortOptions.direction)),e.filters.forEach(function(r){var n=r.model,a=e.$eval(n);if(r.disableUrl)return void(i=!0);if(a){var o;if(a instanceof Date){if(isNaN(a.getTime()))return;o=a.getFullYear()+"-",o+=a.getMonth()<9?"0"+(a.getMonth()+1)+"-":a.getMonth()+1+"-",o+=a.getDate()<10?"0"+a.getDate():a.getDate(),a=o}t+="&"+encodeURIComponent(n)+"="+encodeURIComponent(a)}}),i&&c(),n.path(t)}function s(){var t=n.path().slice(1),i={},r={};if(e.params=i,t.split("&").forEach(function(t){var e=t.split("=");i[e[0]]=e[1],"page"!==e[0]&&"sort"!==e[0]&&"itemsPerPage"!==e[0]&&(r[decodeURIComponent(e[0])]=decodeURIComponent(e[1]))}),e.filters.forEach(function(t){var i=t.model,n=r[i];if(!t.disableUrl){if(~t.filterType.toLowerCase().indexOf("date"))return e.$parent.__evaltmp=n?new Date(n):null,void e.$parent.$eval(i+"=__evaltmp");"select"!==t.filterType||n||(n=""),n&&(e.__evaltmp=n,e.$eval(i+"=__evaltmp"))}}),e.serverPagination||p(),e.paginationOptions.itemsPerPage=e.defaultsPaginationOptions.itemsPerPage,e.paginationOptions.currentPage=e.defaultsPaginationOptions.currentPage,i.itemsPerPage&&(e.paginationOptions.itemsPerPage=i.itemsPerPage),i.page&&(!e.serverPagination&&(i.page-1)*e.paginationOptions.itemsPerPage>e.filtered.length?e.paginationOptions.currentPage=1:e.paginationOptions.currentPage=i.page),i.sort){var a=i.sort.split("-");e.sortOptions.predicate=decodeURIComponent(a[0]),e.sortOptions.direction=decodeURIComponent(a[1])}e.serverPagination||c()}function l(){var t=n.path().slice(1);e._gridOptions.getData("?"+t,function(t,i){e.filtered=t,e.paginationOptions.totalItems=i})}function c(){var t=Date.now(),i=!1;e._time={},e.sortOptions.predicate&&e.sortCache&&e.sortCache.predicate===e.sortOptions.predicate&&e.sortCache.direction===e.sortOptions.direction?(e.filtered=e.sortCache.data.slice(),i=!0):e.filtered=e._gridOptions.data.slice(),e._time.copy=Date.now()-t;var n=Date.now();p(),e._time.filters=Date.now()-n;var a=Date.now();e.sortOptions.predicate&&!i&&(e.filtered=r("orderBy")(e.filtered,e.sortOptions.predicate,"desc"===e.sortOptions.direction),e.sortCache={data:e.filtered.slice(),predicate:e.sortOptions.predicate,direction:e.sortOptions.direction}),e._time.sort=Date.now()-a,e._time.all=Date.now()-t,e.paginationOptions.totalItems=e.filtered.length}function p(){e.filters.forEach(function(t){var i=t.filterBy,r=t.model,n=e.$eval(r),o=t.filterType;if(e.customFilters[r])e.filtered=e.customFilters[r](e.filtered,n,i);else if(n&&o){var s=a.getFilterByType(o);s&&(e.filtered=s(e.filtered,n,i))}})}e._gridOptions=e.$eval(i.attr("grid-options")),e._gridActions=e.$eval(i.attr("grid-actions")),e.serverPagination="true"===i.attr("server-pagination"),e.getDataDelay=i.attr("get-delay")||350,e._gridActions||(e.$parent.$eval(i.attr("grid-actions")+"= {}"),e._gridActions=e.$parent.$eval(i.attr("grid-actions"))),e._gridOptions.grid=e,e.filtered=e._gridOptions.data.slice(),e.paginationOptions=e._gridOptions.pagination?angular.copy(e._gridOptions.pagination):{},e.defaultsPaginationOptions={itemsPerPage:e.paginationOptions.itemsPerPage||"10",currentPage:e.paginationOptions.currentPage||1},e.paginationOptions=angular.copy(e.defaultsPaginationOptions),e.sortOptions=e._gridOptions.sort?angular.copy(e._gridOptions.sort):{},e.customFilters=e._gridOptions.customFilters?angular.copy(e._gridOptions.customFilters):{},e.urlSync=e._gridOptions.urlSync,e.$watch("_gridOptions.data",function(i){i&&i.length&&(e.sortCache={},e.filtered=e._gridOptions.data.slice(),e.filters.forEach(function(i){"select"===i.filterType&&(e[i.model+"Options"]=t(e.filtered,i.filterBy))}),e.urlSync?s(n.path()):c())}),e.sort=function(t){var i=e.sortOptions.predicate===t&&"desc"===e.sortOptions.direction?"asc":"desc";e.sortOptions.predicate=t,e.sortOptions.direction=i,e.paginationOptions.currentPage=1,e.reloadGrid()},e.filter=function(){e.paginationOptions.currentPage=1,e.reloadGrid()},e.$on("$locationChangeSuccess",function(){(e.urlSync||e.serverPagination)&&(e.serverPagination&&(clearTimeout(e.getDataTimeout),e.getDataTimeout=setTimeout(l,e.getDataDelay)),e.filtered&&s(n.path()))}),e.reloadGrid=function(){e.urlSync||e.serverPagination?o():c()},e._gridActions.refresh=e.reloadGrid,e._gridActions.filter=e.filter,e._gridActions.sort=e.sort}]).directive("gridData",["$compile","$animate",function(e){return{restrict:"EA",scope:!0,controller:"gridController",link:function(i,r,n){var a=[],o=[],s=[],l=r.parent(),c=n.id,p="true"===n.serverPagination;angular.forEach(angular.element(l[0].querySelectorAll("[sortable]")),function(t){var r=angular.element(t),n=r.attr("sortable");a.push(r),r.attr("ng-class","{'sort-ascent' : sortOptions.predicate ==='"+n+"' && sortOptions.direction === 'asc', 'sort-descent' : sortOptions.predicate === '"+n+"' && sortOptions.direction === 'desc'}"),r.attr("ng-click","sort('"+n+"')"),e(r)(i)}),angular.forEach(angular.element(document.querySelectorAll("[filter-by]")),function(e){var n=angular.element(e),a=l.find(n).length>0,s=n.attr("filter-by"),p=n.attr("filter-type")||"",g=n.attr("ng-model"),d=n.attr("disable-url");c&&n.attr("grid-id")&&c!=n.attr("grid-id")||("select"!==p||(i[g+"Options"]=t(i.$eval(r.attr("grid-options")+".data"),s)),!~p.indexOf("date")||n.attr("ng-focus")||n.attr("ng-blur")||(n.attr("ng-focus","filter('{"+g+" : this."+g+"}')"),n.attr("ng-blur","filter('{"+g+" : this."+g+"}')")),g||(g=s,n.attr("ng-model",s),n.attr("ng-change","filter()")),o.push({model:g,isInScope:a,filterBy:s,filterType:p,disableUrl:d}))}),angular.forEach(angular.element(l[0].querySelectorAll("[grid-item]")),function(t){var r=angular.element(t);s.push(r),p?r.attr("ng-repeat","item in filtered"):r.attr("ng-repeat","item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage track by $index"),e(r)(i)}),i.sorting=a,i.rows=s,i.filters=o}}}]).factory("filtersFactory",function(){function t(t,e,i){return t.filter(function(t){return e&&t[i]?t[i]===e:!0})}function e(t,e,i){return t.filter(function(t){return e&&t[i]?~(t[i]+"").toLowerCase().indexOf((e+"").toLowerCase()):!0})}function i(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]<=e+86399999:!0})}function r(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]>=e:!0})}return{getFilterByType:function(n){switch(n){case"select":return t;case"text":return e;case"dateTo":return i;case"dateFrom":return r;default:return null}}}})}(); \ No newline at end of file +!function(){"use strict";function t(t,e){var i=[];return t?(t.forEach(function(t){~i.indexOf(t[e])||i.push(t[e])}),i.map(function(t){return{text:t,value:t}})):void 0}angular.module("dataGrid",[]).filter("startFrom",function(){return function(t,e){return t?(e=+e,t.slice(e)):[]}}).controller("gridController",["$scope","$element","$filter","$location","filtersFactory",function(e,i,r,n,a){function o(){var t,i=!1;t="page="+e.paginationOptions.currentPage,e.paginationOptions.itemsPerPage!==e.defaultsPaginationOptions.itemsPerPage&&(t+="&itemsPerPage="+e.paginationOptions.itemsPerPage),e.sortOptions.predicate&&(t+="&sort="+encodeURIComponent(e.sortOptions.predicate+"-"+e.sortOptions.direction)),e.filters.forEach(function(r){var n=r.model,a=e.$eval(n);if(r.disableUrl)return void(i=!0);if(a){var o;if(a instanceof Date){if(isNaN(a.getTime()))return;o=a.getFullYear()+"-",o+=a.getMonth()<9?"0"+(a.getMonth()+1)+"-":a.getMonth()+1+"-",o+=a.getDate()<10?"0"+a.getDate():a.getDate(),a=o}t+="&"+encodeURIComponent(n)+"="+encodeURIComponent(a)}}),i&&c(),n.path(t)}function s(){var t=n.path().slice(1),i={},r={};if(e.params=i,t.split("&").forEach(function(t){var e=t.split("=");i[e[0]]=e[1],"page"!==e[0]&&"sort"!==e[0]&&"itemsPerPage"!==e[0]&&(r[decodeURIComponent(e[0])]=decodeURIComponent(e[1]))}),e.filters.forEach(function(t){var i=t.model,n=r[i];if(!t.disableUrl){if(~t.filterType.toLowerCase().indexOf("date"))return e.$parent.__evaltmp=n?new Date(n):null,void e.$parent.$eval(i+"=__evaltmp");"select"!==t.filterType||n||(n=""),n&&(e.__evaltmp=n,e.$eval(i+"=__evaltmp"))}}),e.serverPagination||p(),e.paginationOptions.itemsPerPage=e.defaultsPaginationOptions.itemsPerPage,e.paginationOptions.currentPage=e.defaultsPaginationOptions.currentPage,i.itemsPerPage&&(e.paginationOptions.itemsPerPage=i.itemsPerPage),i.page&&(!e.serverPagination&&(i.page-1)*e.paginationOptions.itemsPerPage>e.filtered.length?e.paginationOptions.currentPage=1:e.paginationOptions.currentPage=i.page),i.sort){var a=i.sort.split("-");e.sortOptions.predicate=decodeURIComponent(a[0]),e.sortOptions.direction=decodeURIComponent(a[1])}e.serverPagination||c()}function l(){var t=n.path().slice(1);e._gridOptions.getData("?"+t,function(t,i){e.filtered=t,e.paginationOptions.totalItems=i})}function c(){var t=Date.now(),i=!1;e._time={},e.sortOptions.predicate&&e.sortCache&&e.sortCache.predicate===e.sortOptions.predicate&&e.sortCache.direction===e.sortOptions.direction?(e.filtered=e.sortCache.data.slice(),i=!0):e.filtered=e._gridOptions.data.slice(),e._time.copy=Date.now()-t;var n=Date.now();p(),e._time.filters=Date.now()-n;var a=Date.now();e.sortOptions.predicate&&!i&&(e.filtered=r("orderBy")(e.filtered,e.sortOptions.predicate,"desc"===e.sortOptions.direction),e.sortCache={data:e.filtered.slice(),predicate:e.sortOptions.predicate,direction:e.sortOptions.direction}),e._time.sort=Date.now()-a,e._time.all=Date.now()-t,e.paginationOptions.totalItems=e.filtered.length}function p(){e.filters.forEach(function(t){var i=t.filterBy,r=t.model,n=e.$eval(r),o=t.filterType;if(e.customFilters[r])e.filtered=e.customFilters[r](e.filtered,n,i);else if(n&&o){var s=a.getFilterByType(o);s&&(e.filtered=s(e.filtered,n,i))}})}e._gridOptions=e.$eval(i.attr("grid-options")),e._gridActions=e.$eval(i.attr("grid-actions")),e.serverPagination="true"===i.attr("server-pagination"),e.getDataDelay=i.attr("get-delay")||350,e._gridActions||(e.$parent.$eval(i.attr("grid-actions")+"= {}"),e._gridActions=e.$parent.$eval(i.attr("grid-actions"))),e._gridOptions.grid=e,e.filtered=e._gridOptions.data.slice(),e.paginationOptions=e._gridOptions.pagination?angular.copy(e._gridOptions.pagination):{},e.defaultsPaginationOptions={itemsPerPage:e.paginationOptions.itemsPerPage||"10",currentPage:e.paginationOptions.currentPage||1},e.paginationOptions=angular.copy(e.defaultsPaginationOptions),e.sortOptions=e._gridOptions.sort?angular.copy(e._gridOptions.sort):{},e.customFilters=e._gridOptions.customFilters?angular.copy(e._gridOptions.customFilters):{},e.urlSync=e._gridOptions.urlSync,e.$watch("_gridOptions.data",function(i){i&&i.length&&(e.sortCache={},e.filtered=e._gridOptions.data.slice(),e.filters.forEach(function(i){"select"===i.filterType&&(e[i.model+"Options"]=t(e.filtered,i.filterBy))}),e.urlSync?s(n.path()):c())}),e.sort=function(t){var i=e.sortOptions.predicate===t&&"desc"===e.sortOptions.direction?"asc":"desc";e.sortOptions.predicate=t,e.sortOptions.direction=i,e.paginationOptions.currentPage=1,e.reloadGrid()},e.filter=function(){e.paginationOptions.currentPage=1,e.reloadGrid()},e.$on("$locationChangeSuccess",function(){(e.urlSync||e.serverPagination)&&(e.serverPagination&&(clearTimeout(e.getDataTimeout),e.getDataTimeout=setTimeout(l,e.getDataDelay)),e.filtered&&s(n.path()))}),e.reloadGrid=function(){e.urlSync||e.serverPagination?o():c()},e._gridActions.refresh=e.reloadGrid,e._gridActions.filter=e.filter,e._gridActions.sort=e.sort}]).directive("gridData",["$compile","$animate",function(e){return{restrict:"EA",scope:!0,controller:"gridController",link:function(i,r,n){var a=[],o=[],s=[],l=r.parent(),c=n.id,p="true"===n.serverPagination;angular.forEach(angular.element(l[0].querySelectorAll("[sortable]")),function(t){var r=angular.element(t),n=r.attr("sortable");a.push(r),r.attr("ng-class","{'sort-ascent' : sortOptions.predicate ==='"+n+"' && sortOptions.direction === 'asc', 'sort-descent' : sortOptions.predicate === '"+n+"' && sortOptions.direction === 'desc'}"),r.attr("ng-click","sort('"+n+"')"),e(r)(i)}),angular.forEach(angular.element(document.querySelectorAll("[filter-by]")),function(e){var n=angular.element(e),a=l.find(n).length>0,s=n.attr("filter-by"),p=n.attr("filter-type")||"",g=n.attr("ng-model"),d=n.attr("disable-url");c&&n.attr("grid-id")&&c!=n.attr("grid-id")||("select"!==p||(i[g+"Options"]=t(i.$eval(r.attr("grid-options")+".data"),s)),!~p.indexOf("date")||n.attr("ng-focus")||n.attr("ng-blur")||(n.attr("ng-focus","filter('{"+g+" : this."+g+"}')"),n.attr("ng-blur","filter('{"+g+" : this."+g+"}')")),g||(g=s,n.attr("ng-model",s),n.attr("ng-change","filter()")),o.push({model:g,isInScope:a,filterBy:s,filterType:p,disableUrl:d}))}),angular.forEach(angular.element(l[0].querySelectorAll("[grid-item]")),function(t){var r=angular.element(t);s.push(r),p?r.attr("ng-repeat","item in filtered"):r.attr("ng-repeat","item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage track by $index"),e(r)(i)}),i.sorting=a,i.rows=s,i.filters=o}}}]).factory("filtersFactory",function(){function t(t,e,i){return t.filter(function(t){return e&&t[i]?t[i]===e:!0})}function e(t,e,i){return t.filter(function(t){return e&&t[i]?~(t[i]+"").toLowerCase().indexOf((e+"").toLowerCase()):!!t[i]})}function i(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]<=e+86399999:!0})}function r(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]>=e:!0})}return{getFilterByType:function(n){switch(n){case"select":return t;case"text":return e;case"dateTo":return i;case"dateFrom":return r;default:return null}}}})}(); \ No newline at end of file diff --git a/src/js/dataGrid.js b/src/js/dataGrid.js index 7586454..a5bdfeb 100644 --- a/src/js/dataGrid.js +++ b/src/js/dataGrid.js @@ -365,7 +365,7 @@ function textFilter(items, value, predicate) { return items.filter(function (item) { - return value && item[predicate] ? ~(item[predicate] + '').toLowerCase().indexOf((value + '').toLowerCase()) : true; + return value && item[predicate] ? ~(item[predicate] + '').toLowerCase().indexOf((value + '').toLowerCase()) : !!item[predicate]; }); } From 763b390c3af47cee50eb6790c607f09324cb1d12 Mon Sep 17 00:00:00 2001 From: skozlov Date: Tue, 7 Jun 2016 13:18:32 +0300 Subject: [PATCH 08/53] Init commit --- demo/bootstrap/js/serverPaginationApp.js | 38 ++++++++++ demo/bootstrap/server-pagination.html | 88 ++++++++++++++++++++++++ dist/dataGrid.js | 2 +- src/js/dataGrid.js | 2 +- 4 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 demo/bootstrap/js/serverPaginationApp.js create mode 100644 demo/bootstrap/server-pagination.html diff --git a/demo/bootstrap/js/serverPaginationApp.js b/demo/bootstrap/js/serverPaginationApp.js new file mode 100644 index 0000000..d814962 --- /dev/null +++ b/demo/bootstrap/js/serverPaginationApp.js @@ -0,0 +1,38 @@ +(function () { + 'use strict'; + + angular + .module('myApp', ['ui.bootstrap', 'dataGrid', 'pagination']) + .controller('myAppController', MyAppController) + .factory('myAppFactory', MyAppFactory); + + MyAppController.$inject = ['$scope', 'myAppFactory']; + MyAppFactory.$inject = ['$http']; + + function MyAppController($scope, myAppFactory) { + + $scope.gridOptions = { + data: [], + getData: myAppFactory.getUsersData, + sort: { + predicate: 'name', + direction: 'asc' + } + }; + $scope.gridActions = {}; + + } + + function MyAppFactory($http) { + var herokuDomain = 'https://server-pagination.herokuapp.com'; + return { + getUsersData: getUsersData + }; + + function getUsersData(params, callback) { + $http.get(herokuDomain + '/users' + params).success(function (response) { + callback(response.users, response.usersCount); + }); + } + } +})(); diff --git a/demo/bootstrap/server-pagination.html b/demo/bootstrap/server-pagination.html new file mode 100644 index 0000000..957a7d3 --- /dev/null +++ b/demo/bootstrap/server-pagination.html @@ -0,0 +1,88 @@ + + + + + + + + + +
+
+
+
+ + +
+
+
+
+ + + + + + + + + + + + + +
NameSurname
{{item.name}}{{item.surname}}
+
+
+
+
+
+ + +
+
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/dist/dataGrid.js b/dist/dataGrid.js index a5bdfeb..5ce3549 100644 --- a/dist/dataGrid.js +++ b/dist/dataGrid.js @@ -329,7 +329,7 @@ element.attr('ng-change', 'filter()'); //$compile(element)($scope); } - + $compile(element)($scope); filters.push({ model: urlName, isInScope: isInScope, diff --git a/src/js/dataGrid.js b/src/js/dataGrid.js index a5bdfeb..5ce3549 100644 --- a/src/js/dataGrid.js +++ b/src/js/dataGrid.js @@ -329,7 +329,7 @@ element.attr('ng-change', 'filter()'); //$compile(element)($scope); } - + $compile(element)($scope); filters.push({ model: urlName, isInScope: isInScope, From d7c3bf891f53324c822dddd5c2e9bccaf368d303 Mon Sep 17 00:00:00 2001 From: skozlov Date: Thu, 9 Jun 2016 14:17:36 +0300 Subject: [PATCH 09/53] Order server pagination --- demo/bootstrap/js/serverPaginationApp.js | 11 +- demo/bootstrap/server-pagination.html | 175 ++++++++++++++++++----- 2 files changed, 147 insertions(+), 39 deletions(-) diff --git a/demo/bootstrap/js/serverPaginationApp.js b/demo/bootstrap/js/serverPaginationApp.js index d814962..a88ef6a 100644 --- a/demo/bootstrap/js/serverPaginationApp.js +++ b/demo/bootstrap/js/serverPaginationApp.js @@ -13,25 +13,24 @@ $scope.gridOptions = { data: [], - getData: myAppFactory.getUsersData, + getData: myAppFactory.getOrdersData, sort: { predicate: 'name', direction: 'asc' } }; $scope.gridActions = {}; - } function MyAppFactory($http) { var herokuDomain = 'https://server-pagination.herokuapp.com'; return { - getUsersData: getUsersData + getOrdersData: getOrdersData }; - function getUsersData(params, callback) { - $http.get(herokuDomain + '/users' + params).success(function (response) { - callback(response.users, response.usersCount); + function getOrdersData(params, callback) { + $http.get(herokuDomain + '/orders' + params).success(function (response) { + callback(response.orders, response.ordersCount); }); } } diff --git a/demo/bootstrap/server-pagination.html b/demo/bootstrap/server-pagination.html index 957a7d3..19e58b2 100644 --- a/demo/bootstrap/server-pagination.html +++ b/demo/bootstrap/server-pagination.html @@ -19,69 +19,178 @@ vertical-align: top; } - + + + +
+
-
-
- - +
+
+
+ + +
+
+
+
+ + +
+ + + + +
+
+
+
+
+ + +
+ + + + +
+
+
+ +
+
+
{{paginationOptions.totalItems}} items total
+
+
+
+
+
+
+
+ + +
+
+
+
+ - - + + + + - - + + + +
NameSurnameOrder #Date PlacedStatusesTotal
{{item.name}}{{item.surname}}{{item.orderNo}}{{item.datePlaced | date:'MM/dd/yyyy'}}{{item.status}}{{item.total}}
-
-
-
-
- - -
+
{{paginationOptions.totalItems}} items total
+
+
+
+
+
+
+
+ + +
+
+ - - + + From 271576f99a7c62b04d96baea7f7124370d2e45e2 Mon Sep 17 00:00:00 2001 From: skozlov Date: Thu, 9 Jun 2016 18:07:49 +0300 Subject: [PATCH 10/53] Filter input is fixed --- src/js/dataGrid.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/js/dataGrid.js b/src/js/dataGrid.js index 5ce3549..6fa8ff7 100644 --- a/src/js/dataGrid.js +++ b/src/js/dataGrid.js @@ -107,7 +107,7 @@ //custom filters $scope.filters.forEach(function (filter) { var urlName = filter.model, - value = $scope.$eval(urlName); + value = filter.isInScope ? $scope.$eval(urlName) : $scope.$parent.$eval(urlName); if (filter.disableUrl) { needApplyFilters = true; @@ -173,8 +173,13 @@ } if (value) { - $scope.__evaltmp = value; - $scope.$eval(urlName + '=__evaltmp'); + if (filter.isInScope) { + $scope.__evaltmp = value; + $scope.$eval(urlName + '=__evaltmp'); + } else { + $scope.$parent.__evaltmp = value; + $scope.$parent.$eval(urlName + '=__evaltmp'); + } } }); @@ -260,7 +265,7 @@ $scope.filters.forEach(function (filter) { var predicate = filter.filterBy, urlName = filter.model, - value = $scope.$eval(urlName), + value = filter.isInScope ? $scope.$eval(urlName) : $scope.$parent.$eval(urlName), type = filter.filterType; if ($scope.customFilters[urlName]) { $scope.filtered = $scope.customFilters[urlName]($scope.filtered, value, predicate); @@ -302,7 +307,7 @@ angular.forEach(angular.element(document.querySelectorAll('[filter-by]')), function (filter) { var element = angular.element(filter), - isInScope = directiveElement.find(element).length > 0, + isInScope = $element.find(element).length > 0, predicate = element.attr('filter-by'), filterType = element.attr('filter-type') || '', urlName = element.attr('ng-model'), @@ -329,7 +334,7 @@ element.attr('ng-change', 'filter()'); //$compile(element)($scope); } - $compile(element)($scope); + //$compile(element)($scope); filters.push({ model: urlName, isInScope: isInScope, From 69eb586e46be46928d56cecf21e1068ce3ef43b1 Mon Sep 17 00:00:00 2001 From: skozlov Date: Mon, 13 Jun 2016 14:00:50 +0300 Subject: [PATCH 11/53] Were added statuses request for ordres and default sorting for server pagination --- demo/bootstrap/index.html | 2 +- demo/bootstrap/js/serverPaginationApp.js | 13 +++++++++++-- demo/bootstrap/server-pagination.html | 19 +++++++++++++++---- src/js/dataGrid.js | 22 ++++++++++++++-------- 4 files changed, 41 insertions(+), 15 deletions(-) diff --git a/demo/bootstrap/index.html b/demo/bootstrap/index.html index c2cf1d0..604e99b 100644 --- a/demo/bootstrap/index.html +++ b/demo/bootstrap/index.html @@ -168,7 +168,7 @@

Additional Demos

ng-model="status" ng-change="filter()"> - diff --git a/demo/bootstrap/js/serverPaginationApp.js b/demo/bootstrap/js/serverPaginationApp.js index a88ef6a..dc46500 100644 --- a/demo/bootstrap/js/serverPaginationApp.js +++ b/demo/bootstrap/js/serverPaginationApp.js @@ -15,17 +15,22 @@ data: [], getData: myAppFactory.getOrdersData, sort: { - predicate: 'name', + predicate: 'orderNo', direction: 'asc' } }; + $scope.UI = {}; $scope.gridActions = {}; + myAppFactory.getStatuses().success(function (resp) { + $scope.UI.statusOptions = resp; + }); } function MyAppFactory($http) { var herokuDomain = 'https://server-pagination.herokuapp.com'; return { - getOrdersData: getOrdersData + getOrdersData: getOrdersData, + getStatuses: getStatuses }; function getOrdersData(params, callback) { @@ -33,5 +38,9 @@ callback(response.orders, response.ordersCount); }); } + + function getStatuses() { + return $http.get(herokuDomain + '/orders/statuses'); + } } })(); diff --git a/demo/bootstrap/server-pagination.html b/demo/bootstrap/server-pagination.html index 19e58b2..40f232c 100644 --- a/demo/bootstrap/server-pagination.html +++ b/demo/bootstrap/server-pagination.html @@ -137,10 +137,21 @@ - - - - + + + + diff --git a/src/js/dataGrid.js b/src/js/dataGrid.js index 6fa8ff7..8688c79 100644 --- a/src/js/dataGrid.js +++ b/src/js/dataGrid.js @@ -55,10 +55,12 @@ } }); - $scope.sort = function (predicate) { - var direction = $scope.sortOptions.predicate === predicate && $scope.sortOptions.direction === 'desc' ? 'asc' : 'desc'; - $scope.sortOptions.predicate = predicate; - $scope.sortOptions.direction = direction; + $scope.sort = function (predicate, isDefaultSort) { + if (!isDefaultSort) { + var direction = $scope.sortOptions.predicate === predicate && $scope.sortOptions.direction === 'desc' ? 'asc' : 'desc'; + $scope.sortOptions.direction = direction; + $scope.sortOptions.predicate = predicate; + } $scope.paginationOptions.currentPage = 1; $scope.reloadGrid(); }; @@ -217,10 +219,14 @@ function getData() { var url = $location.path().slice(1); - $scope._gridOptions.getData('?' + url, function (data, totalItems) { - $scope.filtered = data; - $scope.paginationOptions.totalItems = totalItems; - }); + if (!url && $scope.sortOptions.predicate) { + $scope.sort($scope.sortOptions.predicate, true); + } else { + $scope._gridOptions.getData('?' + url, function (data, totalItems) { + $scope.filtered = data; + $scope.paginationOptions.totalItems = totalItems; + }); + } // -> to promise //$scope._gridOptions.getData('?' + url).then(function (data, totalItems) { // $scope.filtered = data; From 38844a964285e2bd6beae5c1a78aeedf7ef78fc9 Mon Sep 17 00:00:00 2001 From: skozlov Date: Mon, 13 Jun 2016 14:02:57 +0300 Subject: [PATCH 12/53] Commit dist dataGrid.js --- dist/dataGrid.js | 39 +++++++++++++++++++++++++-------------- dist/dataGrid.min.js | 2 +- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/dist/dataGrid.js b/dist/dataGrid.js index 5ce3549..8688c79 100644 --- a/dist/dataGrid.js +++ b/dist/dataGrid.js @@ -55,10 +55,12 @@ } }); - $scope.sort = function (predicate) { - var direction = $scope.sortOptions.predicate === predicate && $scope.sortOptions.direction === 'desc' ? 'asc' : 'desc'; - $scope.sortOptions.predicate = predicate; - $scope.sortOptions.direction = direction; + $scope.sort = function (predicate, isDefaultSort) { + if (!isDefaultSort) { + var direction = $scope.sortOptions.predicate === predicate && $scope.sortOptions.direction === 'desc' ? 'asc' : 'desc'; + $scope.sortOptions.direction = direction; + $scope.sortOptions.predicate = predicate; + } $scope.paginationOptions.currentPage = 1; $scope.reloadGrid(); }; @@ -107,7 +109,7 @@ //custom filters $scope.filters.forEach(function (filter) { var urlName = filter.model, - value = $scope.$eval(urlName); + value = filter.isInScope ? $scope.$eval(urlName) : $scope.$parent.$eval(urlName); if (filter.disableUrl) { needApplyFilters = true; @@ -173,8 +175,13 @@ } if (value) { - $scope.__evaltmp = value; - $scope.$eval(urlName + '=__evaltmp'); + if (filter.isInScope) { + $scope.__evaltmp = value; + $scope.$eval(urlName + '=__evaltmp'); + } else { + $scope.$parent.__evaltmp = value; + $scope.$parent.$eval(urlName + '=__evaltmp'); + } } }); @@ -212,10 +219,14 @@ function getData() { var url = $location.path().slice(1); - $scope._gridOptions.getData('?' + url, function (data, totalItems) { - $scope.filtered = data; - $scope.paginationOptions.totalItems = totalItems; - }); + if (!url && $scope.sortOptions.predicate) { + $scope.sort($scope.sortOptions.predicate, true); + } else { + $scope._gridOptions.getData('?' + url, function (data, totalItems) { + $scope.filtered = data; + $scope.paginationOptions.totalItems = totalItems; + }); + } // -> to promise //$scope._gridOptions.getData('?' + url).then(function (data, totalItems) { // $scope.filtered = data; @@ -260,7 +271,7 @@ $scope.filters.forEach(function (filter) { var predicate = filter.filterBy, urlName = filter.model, - value = $scope.$eval(urlName), + value = filter.isInScope ? $scope.$eval(urlName) : $scope.$parent.$eval(urlName), type = filter.filterType; if ($scope.customFilters[urlName]) { $scope.filtered = $scope.customFilters[urlName]($scope.filtered, value, predicate); @@ -302,7 +313,7 @@ angular.forEach(angular.element(document.querySelectorAll('[filter-by]')), function (filter) { var element = angular.element(filter), - isInScope = directiveElement.find(element).length > 0, + isInScope = $element.find(element).length > 0, predicate = element.attr('filter-by'), filterType = element.attr('filter-type') || '', urlName = element.attr('ng-model'), @@ -329,7 +340,7 @@ element.attr('ng-change', 'filter()'); //$compile(element)($scope); } - $compile(element)($scope); + //$compile(element)($scope); filters.push({ model: urlName, isInScope: isInScope, diff --git a/dist/dataGrid.min.js b/dist/dataGrid.min.js index e9c6a48..7790baf 100644 --- a/dist/dataGrid.min.js +++ b/dist/dataGrid.min.js @@ -1 +1 @@ -!function(){"use strict";function t(t,e){var i=[];return t?(t.forEach(function(t){~i.indexOf(t[e])||i.push(t[e])}),i.map(function(t){return{text:t,value:t}})):void 0}angular.module("dataGrid",[]).filter("startFrom",function(){return function(t,e){return t?(e=+e,t.slice(e)):[]}}).controller("gridController",["$scope","$element","$filter","$location","filtersFactory",function(e,i,r,n,a){function o(){var t,i=!1;t="page="+e.paginationOptions.currentPage,e.paginationOptions.itemsPerPage!==e.defaultsPaginationOptions.itemsPerPage&&(t+="&itemsPerPage="+e.paginationOptions.itemsPerPage),e.sortOptions.predicate&&(t+="&sort="+encodeURIComponent(e.sortOptions.predicate+"-"+e.sortOptions.direction)),e.filters.forEach(function(r){var n=r.model,a=e.$eval(n);if(r.disableUrl)return void(i=!0);if(a){var o;if(a instanceof Date){if(isNaN(a.getTime()))return;o=a.getFullYear()+"-",o+=a.getMonth()<9?"0"+(a.getMonth()+1)+"-":a.getMonth()+1+"-",o+=a.getDate()<10?"0"+a.getDate():a.getDate(),a=o}t+="&"+encodeURIComponent(n)+"="+encodeURIComponent(a)}}),i&&c(),n.path(t)}function s(){var t=n.path().slice(1),i={},r={};if(e.params=i,t.split("&").forEach(function(t){var e=t.split("=");i[e[0]]=e[1],"page"!==e[0]&&"sort"!==e[0]&&"itemsPerPage"!==e[0]&&(r[decodeURIComponent(e[0])]=decodeURIComponent(e[1]))}),e.filters.forEach(function(t){var i=t.model,n=r[i];if(!t.disableUrl){if(~t.filterType.toLowerCase().indexOf("date"))return e.$parent.__evaltmp=n?new Date(n):null,void e.$parent.$eval(i+"=__evaltmp");"select"!==t.filterType||n||(n=""),n&&(e.__evaltmp=n,e.$eval(i+"=__evaltmp"))}}),e.serverPagination||p(),e.paginationOptions.itemsPerPage=e.defaultsPaginationOptions.itemsPerPage,e.paginationOptions.currentPage=e.defaultsPaginationOptions.currentPage,i.itemsPerPage&&(e.paginationOptions.itemsPerPage=i.itemsPerPage),i.page&&(!e.serverPagination&&(i.page-1)*e.paginationOptions.itemsPerPage>e.filtered.length?e.paginationOptions.currentPage=1:e.paginationOptions.currentPage=i.page),i.sort){var a=i.sort.split("-");e.sortOptions.predicate=decodeURIComponent(a[0]),e.sortOptions.direction=decodeURIComponent(a[1])}e.serverPagination||c()}function l(){var t=n.path().slice(1);e._gridOptions.getData("?"+t,function(t,i){e.filtered=t,e.paginationOptions.totalItems=i})}function c(){var t=Date.now(),i=!1;e._time={},e.sortOptions.predicate&&e.sortCache&&e.sortCache.predicate===e.sortOptions.predicate&&e.sortCache.direction===e.sortOptions.direction?(e.filtered=e.sortCache.data.slice(),i=!0):e.filtered=e._gridOptions.data.slice(),e._time.copy=Date.now()-t;var n=Date.now();p(),e._time.filters=Date.now()-n;var a=Date.now();e.sortOptions.predicate&&!i&&(e.filtered=r("orderBy")(e.filtered,e.sortOptions.predicate,"desc"===e.sortOptions.direction),e.sortCache={data:e.filtered.slice(),predicate:e.sortOptions.predicate,direction:e.sortOptions.direction}),e._time.sort=Date.now()-a,e._time.all=Date.now()-t,e.paginationOptions.totalItems=e.filtered.length}function p(){e.filters.forEach(function(t){var i=t.filterBy,r=t.model,n=e.$eval(r),o=t.filterType;if(e.customFilters[r])e.filtered=e.customFilters[r](e.filtered,n,i);else if(n&&o){var s=a.getFilterByType(o);s&&(e.filtered=s(e.filtered,n,i))}})}e._gridOptions=e.$eval(i.attr("grid-options")),e._gridActions=e.$eval(i.attr("grid-actions")),e.serverPagination="true"===i.attr("server-pagination"),e.getDataDelay=i.attr("get-delay")||350,e._gridActions||(e.$parent.$eval(i.attr("grid-actions")+"= {}"),e._gridActions=e.$parent.$eval(i.attr("grid-actions"))),e._gridOptions.grid=e,e.filtered=e._gridOptions.data.slice(),e.paginationOptions=e._gridOptions.pagination?angular.copy(e._gridOptions.pagination):{},e.defaultsPaginationOptions={itemsPerPage:e.paginationOptions.itemsPerPage||"10",currentPage:e.paginationOptions.currentPage||1},e.paginationOptions=angular.copy(e.defaultsPaginationOptions),e.sortOptions=e._gridOptions.sort?angular.copy(e._gridOptions.sort):{},e.customFilters=e._gridOptions.customFilters?angular.copy(e._gridOptions.customFilters):{},e.urlSync=e._gridOptions.urlSync,e.$watch("_gridOptions.data",function(i){i&&i.length&&(e.sortCache={},e.filtered=e._gridOptions.data.slice(),e.filters.forEach(function(i){"select"===i.filterType&&(e[i.model+"Options"]=t(e.filtered,i.filterBy))}),e.urlSync?s(n.path()):c())}),e.sort=function(t){var i=e.sortOptions.predicate===t&&"desc"===e.sortOptions.direction?"asc":"desc";e.sortOptions.predicate=t,e.sortOptions.direction=i,e.paginationOptions.currentPage=1,e.reloadGrid()},e.filter=function(){e.paginationOptions.currentPage=1,e.reloadGrid()},e.$on("$locationChangeSuccess",function(){(e.urlSync||e.serverPagination)&&(e.serverPagination&&(clearTimeout(e.getDataTimeout),e.getDataTimeout=setTimeout(l,e.getDataDelay)),e.filtered&&s(n.path()))}),e.reloadGrid=function(){e.urlSync||e.serverPagination?o():c()},e._gridActions.refresh=e.reloadGrid,e._gridActions.filter=e.filter,e._gridActions.sort=e.sort}]).directive("gridData",["$compile","$animate",function(e){return{restrict:"EA",scope:!0,controller:"gridController",link:function(i,r,n){var a=[],o=[],s=[],l=r.parent(),c=n.id,p="true"===n.serverPagination;angular.forEach(angular.element(l[0].querySelectorAll("[sortable]")),function(t){var r=angular.element(t),n=r.attr("sortable");a.push(r),r.attr("ng-class","{'sort-ascent' : sortOptions.predicate ==='"+n+"' && sortOptions.direction === 'asc', 'sort-descent' : sortOptions.predicate === '"+n+"' && sortOptions.direction === 'desc'}"),r.attr("ng-click","sort('"+n+"')"),e(r)(i)}),angular.forEach(angular.element(document.querySelectorAll("[filter-by]")),function(e){var n=angular.element(e),a=l.find(n).length>0,s=n.attr("filter-by"),p=n.attr("filter-type")||"",g=n.attr("ng-model"),d=n.attr("disable-url");c&&n.attr("grid-id")&&c!=n.attr("grid-id")||("select"!==p||(i[g+"Options"]=t(i.$eval(r.attr("grid-options")+".data"),s)),!~p.indexOf("date")||n.attr("ng-focus")||n.attr("ng-blur")||(n.attr("ng-focus","filter('{"+g+" : this."+g+"}')"),n.attr("ng-blur","filter('{"+g+" : this."+g+"}')")),g||(g=s,n.attr("ng-model",s),n.attr("ng-change","filter()")),o.push({model:g,isInScope:a,filterBy:s,filterType:p,disableUrl:d}))}),angular.forEach(angular.element(l[0].querySelectorAll("[grid-item]")),function(t){var r=angular.element(t);s.push(r),p?r.attr("ng-repeat","item in filtered"):r.attr("ng-repeat","item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage track by $index"),e(r)(i)}),i.sorting=a,i.rows=s,i.filters=o}}}]).factory("filtersFactory",function(){function t(t,e,i){return t.filter(function(t){return e&&t[i]?t[i]===e:!0})}function e(t,e,i){return t.filter(function(t){return e&&t[i]?~(t[i]+"").toLowerCase().indexOf((e+"").toLowerCase()):!!t[i]})}function i(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]<=e+86399999:!0})}function r(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]>=e:!0})}return{getFilterByType:function(n){switch(n){case"select":return t;case"text":return e;case"dateTo":return i;case"dateFrom":return r;default:return null}}}})}(); \ No newline at end of file +!function(){"use strict";function t(t,e){var i=[];return t?(t.forEach(function(t){~i.indexOf(t[e])||i.push(t[e])}),i.map(function(t){return{text:t,value:t}})):void 0}angular.module("dataGrid",[]).filter("startFrom",function(){return function(t,e){return t?(e=+e,t.slice(e)):[]}}).controller("gridController",["$scope","$element","$filter","$location","filtersFactory",function(e,i,r,n,a){function o(){var t,i=!1;t="page="+e.paginationOptions.currentPage,e.paginationOptions.itemsPerPage!==e.defaultsPaginationOptions.itemsPerPage&&(t+="&itemsPerPage="+e.paginationOptions.itemsPerPage),e.sortOptions.predicate&&(t+="&sort="+encodeURIComponent(e.sortOptions.predicate+"-"+e.sortOptions.direction)),e.filters.forEach(function(r){var n=r.model,a=r.isInScope?e.$eval(n):e.$parent.$eval(n);if(r.disableUrl)return void(i=!0);if(a){var o;if(a instanceof Date){if(isNaN(a.getTime()))return;o=a.getFullYear()+"-",o+=a.getMonth()<9?"0"+(a.getMonth()+1)+"-":a.getMonth()+1+"-",o+=a.getDate()<10?"0"+a.getDate():a.getDate(),a=o}t+="&"+encodeURIComponent(n)+"="+encodeURIComponent(a)}}),i&&c(),n.path(t)}function s(){var t=n.path().slice(1),i={},r={};if(e.params=i,t.split("&").forEach(function(t){var e=t.split("=");i[e[0]]=e[1],"page"!==e[0]&&"sort"!==e[0]&&"itemsPerPage"!==e[0]&&(r[decodeURIComponent(e[0])]=decodeURIComponent(e[1]))}),e.filters.forEach(function(t){var i=t.model,n=r[i];if(!t.disableUrl){if(~t.filterType.toLowerCase().indexOf("date"))return e.$parent.__evaltmp=n?new Date(n):null,void e.$parent.$eval(i+"=__evaltmp");"select"!==t.filterType||n||(n=""),n&&(t.isInScope?(e.__evaltmp=n,e.$eval(i+"=__evaltmp")):(e.$parent.__evaltmp=n,e.$parent.$eval(i+"=__evaltmp")))}}),e.serverPagination||p(),e.paginationOptions.itemsPerPage=e.defaultsPaginationOptions.itemsPerPage,e.paginationOptions.currentPage=e.defaultsPaginationOptions.currentPage,i.itemsPerPage&&(e.paginationOptions.itemsPerPage=i.itemsPerPage),i.page&&(!e.serverPagination&&(i.page-1)*e.paginationOptions.itemsPerPage>e.filtered.length?e.paginationOptions.currentPage=1:e.paginationOptions.currentPage=i.page),i.sort){var a=i.sort.split("-");e.sortOptions.predicate=decodeURIComponent(a[0]),e.sortOptions.direction=decodeURIComponent(a[1])}e.serverPagination||c()}function l(){var t=n.path().slice(1);!t&&e.sortOptions.predicate?e.sort(e.sortOptions.predicate,!0):e._gridOptions.getData("?"+t,function(t,i){e.filtered=t,e.paginationOptions.totalItems=i})}function c(){var t=Date.now(),i=!1;e._time={},e.sortOptions.predicate&&e.sortCache&&e.sortCache.predicate===e.sortOptions.predicate&&e.sortCache.direction===e.sortOptions.direction?(e.filtered=e.sortCache.data.slice(),i=!0):e.filtered=e._gridOptions.data.slice(),e._time.copy=Date.now()-t;var n=Date.now();p(),e._time.filters=Date.now()-n;var a=Date.now();e.sortOptions.predicate&&!i&&(e.filtered=r("orderBy")(e.filtered,e.sortOptions.predicate,"desc"===e.sortOptions.direction),e.sortCache={data:e.filtered.slice(),predicate:e.sortOptions.predicate,direction:e.sortOptions.direction}),e._time.sort=Date.now()-a,e._time.all=Date.now()-t,e.paginationOptions.totalItems=e.filtered.length}function p(){e.filters.forEach(function(t){var i=t.filterBy,r=t.model,n=t.isInScope?e.$eval(r):e.$parent.$eval(r),o=t.filterType;if(e.customFilters[r])e.filtered=e.customFilters[r](e.filtered,n,i);else if(n&&o){var s=a.getFilterByType(o);s&&(e.filtered=s(e.filtered,n,i))}})}e._gridOptions=e.$eval(i.attr("grid-options")),e._gridActions=e.$eval(i.attr("grid-actions")),e.serverPagination="true"===i.attr("server-pagination"),e.getDataDelay=i.attr("get-delay")||350,e._gridActions||(e.$parent.$eval(i.attr("grid-actions")+"= {}"),e._gridActions=e.$parent.$eval(i.attr("grid-actions"))),e._gridOptions.grid=e,e.filtered=e._gridOptions.data.slice(),e.paginationOptions=e._gridOptions.pagination?angular.copy(e._gridOptions.pagination):{},e.defaultsPaginationOptions={itemsPerPage:e.paginationOptions.itemsPerPage||"10",currentPage:e.paginationOptions.currentPage||1},e.paginationOptions=angular.copy(e.defaultsPaginationOptions),e.sortOptions=e._gridOptions.sort?angular.copy(e._gridOptions.sort):{},e.customFilters=e._gridOptions.customFilters?angular.copy(e._gridOptions.customFilters):{},e.urlSync=e._gridOptions.urlSync,e.$watch("_gridOptions.data",function(i){i&&i.length&&(e.sortCache={},e.filtered=e._gridOptions.data.slice(),e.filters.forEach(function(i){"select"===i.filterType&&(e[i.model+"Options"]=t(e.filtered,i.filterBy))}),e.urlSync?s(n.path()):c())}),e.sort=function(t,i){if(!i){var r=e.sortOptions.predicate===t&&"desc"===e.sortOptions.direction?"asc":"desc";e.sortOptions.direction=r,e.sortOptions.predicate=t}e.paginationOptions.currentPage=1,e.reloadGrid()},e.filter=function(){e.paginationOptions.currentPage=1,e.reloadGrid()},e.$on("$locationChangeSuccess",function(){(e.urlSync||e.serverPagination)&&(e.serverPagination&&(clearTimeout(e.getDataTimeout),e.getDataTimeout=setTimeout(l,e.getDataDelay)),e.filtered&&s(n.path()))}),e.reloadGrid=function(){e.urlSync||e.serverPagination?o():c()},e._gridActions.refresh=e.reloadGrid,e._gridActions.filter=e.filter,e._gridActions.sort=e.sort}]).directive("gridData",["$compile","$animate",function(e){return{restrict:"EA",scope:!0,controller:"gridController",link:function(i,r,n){var a=[],o=[],s=[],l=r.parent(),c=n.id,p="true"===n.serverPagination;angular.forEach(angular.element(l[0].querySelectorAll("[sortable]")),function(t){var r=angular.element(t),n=r.attr("sortable");a.push(r),r.attr("ng-class","{'sort-ascent' : sortOptions.predicate ==='"+n+"' && sortOptions.direction === 'asc', 'sort-descent' : sortOptions.predicate === '"+n+"' && sortOptions.direction === 'desc'}"),r.attr("ng-click","sort('"+n+"')"),e(r)(i)}),angular.forEach(angular.element(document.querySelectorAll("[filter-by]")),function(e){var n=angular.element(e),a=r.find(n).length>0,s=n.attr("filter-by"),l=n.attr("filter-type")||"",p=n.attr("ng-model"),d=n.attr("disable-url");c&&n.attr("grid-id")&&c!=n.attr("grid-id")||("select"!==l||(i[p+"Options"]=t(i.$eval(r.attr("grid-options")+".data"),s)),!~l.indexOf("date")||n.attr("ng-focus")||n.attr("ng-blur")||(n.attr("ng-focus","filter('{"+p+" : this."+p+"}')"),n.attr("ng-blur","filter('{"+p+" : this."+p+"}')")),p||(p=s,n.attr("ng-model",s),n.attr("ng-change","filter()")),o.push({model:p,isInScope:a,filterBy:s,filterType:l,disableUrl:d}))}),angular.forEach(angular.element(l[0].querySelectorAll("[grid-item]")),function(t){var r=angular.element(t);s.push(r),p?r.attr("ng-repeat","item in filtered"):r.attr("ng-repeat","item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage track by $index"),e(r)(i)}),i.sorting=a,i.rows=s,i.filters=o}}}]).factory("filtersFactory",function(){function t(t,e,i){return t.filter(function(t){return e&&t[i]?t[i]===e:!0})}function e(t,e,i){return t.filter(function(t){return e&&t[i]?~(t[i]+"").toLowerCase().indexOf((e+"").toLowerCase()):!!t[i]})}function i(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]<=e+86399999:!0})}function r(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]>=e:!0})}return{getFilterByType:function(n){switch(n){case"select":return t;case"text":return e;case"dateTo":return i;case"dateFrom":return r;default:return null}}}})}(); \ No newline at end of file From 7f07d07c7aabc1ad184b13df8a177ba049b46906 Mon Sep 17 00:00:00 2001 From: skozlov Date: Tue, 14 Jun 2016 12:08:02 +0300 Subject: [PATCH 13/53] Was added documentation for server pagination. --- README.md | 10 +++++++--- demo/bootstrap/index.html | 5 ++++- demo/bootstrap/server-pagination.html | 18 ++++++++++++++++-- dist/dataGrid.js | 5 ----- dist/dataGrid.min.js | 2 +- src/js/dataGrid.js | 5 ----- 6 files changed, 28 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 8baf5fe..30c62b2 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,10 @@ Direct download: get ZIP archive [from here](https://github.com/angular-data-gri Then use files from *dist* folder (see below). ### Setup -1. Include scripts in you application: `dataGrid.min.js` and `pagination.min.js` (include the second one only if you need pagination). +1. Include scripts in you application: `angular.min.js`, `dataGrid.min.js` and `pagination.min.js` (include the second one only if you need pagination). ```javascript + ``` @@ -105,7 +106,10 @@ Use this object for calling methods of directive: `sort()`, `filter()`, `refresh }; ``` - - For server side pagination/filtering to fetch data by page: assign ```getData``` method to some function with URL params as 1st parameter and data itself as 2d parameter: + - For server side pagination/filtering to fetch data by page: + 1. add attribute 'server-pagination'=true on element on which you applied directive 'grid-data' + 2. assign ```getData``` method to some function with URL params as 1st parameter and data itself as 2d parameter: + ```javascript $scope.gridOptions = { @@ -145,7 +149,7 @@ $scope.gridOptions = { ### Pagination -You can optionally use `pagination` directive to display paging with previous/next and first/last controls. +You can optionally use `grid-pagination` directive to display paging with previous/next and first/last controls. Directive is built on a base of excellent [Angular UI](https://angular-ui.github.io/bootstrap/) component and shares extensive API: ```HTML diff --git a/demo/bootstrap/index.html b/demo/bootstrap/index.html index 604e99b..90b9860 100644 --- a/demo/bootstrap/index.html +++ b/demo/bootstrap/index.html @@ -42,6 +42,9 @@

Additional Demos

  • Multiple grids on page
  • +
  • + Server pagination +

  • @@ -168,7 +171,7 @@

    Additional Demos

    ng-model="status" ng-change="filter()"> - diff --git a/demo/bootstrap/server-pagination.html b/demo/bootstrap/server-pagination.html index 40f232c..f9b25a8 100644 --- a/demo/bootstrap/server-pagination.html +++ b/demo/bootstrap/server-pagination.html @@ -25,7 +25,21 @@ +
    +
    +

    Angular Data Grid Server Pagination

    + Features enabled: sorting, filtering (using both in-grid and external controls), pagination and items-per-page functionality. + Angular UI Datepicker used for date controls, although you can use any other framework, plugin or styling. + Project GitHub +

    @@ -202,7 +216,7 @@ - - + + \ No newline at end of file diff --git a/dist/dataGrid.js b/dist/dataGrid.js index 8688c79..c85c4e4 100644 --- a/dist/dataGrid.js +++ b/dist/dataGrid.js @@ -185,11 +185,6 @@ } }); - if (!$scope.serverPagination) { - applyCustomFilters(); - } - - //pagination options $scope.paginationOptions.itemsPerPage = $scope.defaultsPaginationOptions.itemsPerPage; $scope.paginationOptions.currentPage = $scope.defaultsPaginationOptions.currentPage; diff --git a/dist/dataGrid.min.js b/dist/dataGrid.min.js index 7790baf..31f08ff 100644 --- a/dist/dataGrid.min.js +++ b/dist/dataGrid.min.js @@ -1 +1 @@ -!function(){"use strict";function t(t,e){var i=[];return t?(t.forEach(function(t){~i.indexOf(t[e])||i.push(t[e])}),i.map(function(t){return{text:t,value:t}})):void 0}angular.module("dataGrid",[]).filter("startFrom",function(){return function(t,e){return t?(e=+e,t.slice(e)):[]}}).controller("gridController",["$scope","$element","$filter","$location","filtersFactory",function(e,i,r,n,a){function o(){var t,i=!1;t="page="+e.paginationOptions.currentPage,e.paginationOptions.itemsPerPage!==e.defaultsPaginationOptions.itemsPerPage&&(t+="&itemsPerPage="+e.paginationOptions.itemsPerPage),e.sortOptions.predicate&&(t+="&sort="+encodeURIComponent(e.sortOptions.predicate+"-"+e.sortOptions.direction)),e.filters.forEach(function(r){var n=r.model,a=r.isInScope?e.$eval(n):e.$parent.$eval(n);if(r.disableUrl)return void(i=!0);if(a){var o;if(a instanceof Date){if(isNaN(a.getTime()))return;o=a.getFullYear()+"-",o+=a.getMonth()<9?"0"+(a.getMonth()+1)+"-":a.getMonth()+1+"-",o+=a.getDate()<10?"0"+a.getDate():a.getDate(),a=o}t+="&"+encodeURIComponent(n)+"="+encodeURIComponent(a)}}),i&&c(),n.path(t)}function s(){var t=n.path().slice(1),i={},r={};if(e.params=i,t.split("&").forEach(function(t){var e=t.split("=");i[e[0]]=e[1],"page"!==e[0]&&"sort"!==e[0]&&"itemsPerPage"!==e[0]&&(r[decodeURIComponent(e[0])]=decodeURIComponent(e[1]))}),e.filters.forEach(function(t){var i=t.model,n=r[i];if(!t.disableUrl){if(~t.filterType.toLowerCase().indexOf("date"))return e.$parent.__evaltmp=n?new Date(n):null,void e.$parent.$eval(i+"=__evaltmp");"select"!==t.filterType||n||(n=""),n&&(t.isInScope?(e.__evaltmp=n,e.$eval(i+"=__evaltmp")):(e.$parent.__evaltmp=n,e.$parent.$eval(i+"=__evaltmp")))}}),e.serverPagination||p(),e.paginationOptions.itemsPerPage=e.defaultsPaginationOptions.itemsPerPage,e.paginationOptions.currentPage=e.defaultsPaginationOptions.currentPage,i.itemsPerPage&&(e.paginationOptions.itemsPerPage=i.itemsPerPage),i.page&&(!e.serverPagination&&(i.page-1)*e.paginationOptions.itemsPerPage>e.filtered.length?e.paginationOptions.currentPage=1:e.paginationOptions.currentPage=i.page),i.sort){var a=i.sort.split("-");e.sortOptions.predicate=decodeURIComponent(a[0]),e.sortOptions.direction=decodeURIComponent(a[1])}e.serverPagination||c()}function l(){var t=n.path().slice(1);!t&&e.sortOptions.predicate?e.sort(e.sortOptions.predicate,!0):e._gridOptions.getData("?"+t,function(t,i){e.filtered=t,e.paginationOptions.totalItems=i})}function c(){var t=Date.now(),i=!1;e._time={},e.sortOptions.predicate&&e.sortCache&&e.sortCache.predicate===e.sortOptions.predicate&&e.sortCache.direction===e.sortOptions.direction?(e.filtered=e.sortCache.data.slice(),i=!0):e.filtered=e._gridOptions.data.slice(),e._time.copy=Date.now()-t;var n=Date.now();p(),e._time.filters=Date.now()-n;var a=Date.now();e.sortOptions.predicate&&!i&&(e.filtered=r("orderBy")(e.filtered,e.sortOptions.predicate,"desc"===e.sortOptions.direction),e.sortCache={data:e.filtered.slice(),predicate:e.sortOptions.predicate,direction:e.sortOptions.direction}),e._time.sort=Date.now()-a,e._time.all=Date.now()-t,e.paginationOptions.totalItems=e.filtered.length}function p(){e.filters.forEach(function(t){var i=t.filterBy,r=t.model,n=t.isInScope?e.$eval(r):e.$parent.$eval(r),o=t.filterType;if(e.customFilters[r])e.filtered=e.customFilters[r](e.filtered,n,i);else if(n&&o){var s=a.getFilterByType(o);s&&(e.filtered=s(e.filtered,n,i))}})}e._gridOptions=e.$eval(i.attr("grid-options")),e._gridActions=e.$eval(i.attr("grid-actions")),e.serverPagination="true"===i.attr("server-pagination"),e.getDataDelay=i.attr("get-delay")||350,e._gridActions||(e.$parent.$eval(i.attr("grid-actions")+"= {}"),e._gridActions=e.$parent.$eval(i.attr("grid-actions"))),e._gridOptions.grid=e,e.filtered=e._gridOptions.data.slice(),e.paginationOptions=e._gridOptions.pagination?angular.copy(e._gridOptions.pagination):{},e.defaultsPaginationOptions={itemsPerPage:e.paginationOptions.itemsPerPage||"10",currentPage:e.paginationOptions.currentPage||1},e.paginationOptions=angular.copy(e.defaultsPaginationOptions),e.sortOptions=e._gridOptions.sort?angular.copy(e._gridOptions.sort):{},e.customFilters=e._gridOptions.customFilters?angular.copy(e._gridOptions.customFilters):{},e.urlSync=e._gridOptions.urlSync,e.$watch("_gridOptions.data",function(i){i&&i.length&&(e.sortCache={},e.filtered=e._gridOptions.data.slice(),e.filters.forEach(function(i){"select"===i.filterType&&(e[i.model+"Options"]=t(e.filtered,i.filterBy))}),e.urlSync?s(n.path()):c())}),e.sort=function(t,i){if(!i){var r=e.sortOptions.predicate===t&&"desc"===e.sortOptions.direction?"asc":"desc";e.sortOptions.direction=r,e.sortOptions.predicate=t}e.paginationOptions.currentPage=1,e.reloadGrid()},e.filter=function(){e.paginationOptions.currentPage=1,e.reloadGrid()},e.$on("$locationChangeSuccess",function(){(e.urlSync||e.serverPagination)&&(e.serverPagination&&(clearTimeout(e.getDataTimeout),e.getDataTimeout=setTimeout(l,e.getDataDelay)),e.filtered&&s(n.path()))}),e.reloadGrid=function(){e.urlSync||e.serverPagination?o():c()},e._gridActions.refresh=e.reloadGrid,e._gridActions.filter=e.filter,e._gridActions.sort=e.sort}]).directive("gridData",["$compile","$animate",function(e){return{restrict:"EA",scope:!0,controller:"gridController",link:function(i,r,n){var a=[],o=[],s=[],l=r.parent(),c=n.id,p="true"===n.serverPagination;angular.forEach(angular.element(l[0].querySelectorAll("[sortable]")),function(t){var r=angular.element(t),n=r.attr("sortable");a.push(r),r.attr("ng-class","{'sort-ascent' : sortOptions.predicate ==='"+n+"' && sortOptions.direction === 'asc', 'sort-descent' : sortOptions.predicate === '"+n+"' && sortOptions.direction === 'desc'}"),r.attr("ng-click","sort('"+n+"')"),e(r)(i)}),angular.forEach(angular.element(document.querySelectorAll("[filter-by]")),function(e){var n=angular.element(e),a=r.find(n).length>0,s=n.attr("filter-by"),l=n.attr("filter-type")||"",p=n.attr("ng-model"),d=n.attr("disable-url");c&&n.attr("grid-id")&&c!=n.attr("grid-id")||("select"!==l||(i[p+"Options"]=t(i.$eval(r.attr("grid-options")+".data"),s)),!~l.indexOf("date")||n.attr("ng-focus")||n.attr("ng-blur")||(n.attr("ng-focus","filter('{"+p+" : this."+p+"}')"),n.attr("ng-blur","filter('{"+p+" : this."+p+"}')")),p||(p=s,n.attr("ng-model",s),n.attr("ng-change","filter()")),o.push({model:p,isInScope:a,filterBy:s,filterType:l,disableUrl:d}))}),angular.forEach(angular.element(l[0].querySelectorAll("[grid-item]")),function(t){var r=angular.element(t);s.push(r),p?r.attr("ng-repeat","item in filtered"):r.attr("ng-repeat","item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage track by $index"),e(r)(i)}),i.sorting=a,i.rows=s,i.filters=o}}}]).factory("filtersFactory",function(){function t(t,e,i){return t.filter(function(t){return e&&t[i]?t[i]===e:!0})}function e(t,e,i){return t.filter(function(t){return e&&t[i]?~(t[i]+"").toLowerCase().indexOf((e+"").toLowerCase()):!!t[i]})}function i(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]<=e+86399999:!0})}function r(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]>=e:!0})}return{getFilterByType:function(n){switch(n){case"select":return t;case"text":return e;case"dateTo":return i;case"dateFrom":return r;default:return null}}}})}(); \ No newline at end of file +!function(){"use strict";function t(t,e){var i=[];return t?(t.forEach(function(t){~i.indexOf(t[e])||i.push(t[e])}),i.map(function(t){return{text:t,value:t}})):void 0}angular.module("dataGrid",[]).filter("startFrom",function(){return function(t,e){return t?(e=+e,t.slice(e)):[]}}).controller("gridController",["$scope","$element","$filter","$location","filtersFactory",function(e,i,r,n,a){function o(){var t,i=!1;t="page="+e.paginationOptions.currentPage,e.paginationOptions.itemsPerPage!==e.defaultsPaginationOptions.itemsPerPage&&(t+="&itemsPerPage="+e.paginationOptions.itemsPerPage),e.sortOptions.predicate&&(t+="&sort="+encodeURIComponent(e.sortOptions.predicate+"-"+e.sortOptions.direction)),e.filters.forEach(function(r){var n=r.model,a=r.isInScope?e.$eval(n):e.$parent.$eval(n);if(r.disableUrl)return void(i=!0);if(a){var o;if(a instanceof Date){if(isNaN(a.getTime()))return;o=a.getFullYear()+"-",o+=a.getMonth()<9?"0"+(a.getMonth()+1)+"-":a.getMonth()+1+"-",o+=a.getDate()<10?"0"+a.getDate():a.getDate(),a=o}t+="&"+encodeURIComponent(n)+"="+encodeURIComponent(a)}}),i&&c(),n.path(t)}function s(){var t=n.path().slice(1),i={},r={};if(e.params=i,t.split("&").forEach(function(t){var e=t.split("=");i[e[0]]=e[1],"page"!==e[0]&&"sort"!==e[0]&&"itemsPerPage"!==e[0]&&(r[decodeURIComponent(e[0])]=decodeURIComponent(e[1]))}),e.filters.forEach(function(t){var i=t.model,n=r[i];if(!t.disableUrl){if(~t.filterType.toLowerCase().indexOf("date"))return e.$parent.__evaltmp=n?new Date(n):null,void e.$parent.$eval(i+"=__evaltmp");"select"!==t.filterType||n||(n=""),n&&(t.isInScope?(e.__evaltmp=n,e.$eval(i+"=__evaltmp")):(e.$parent.__evaltmp=n,e.$parent.$eval(i+"=__evaltmp")))}}),e.paginationOptions.itemsPerPage=e.defaultsPaginationOptions.itemsPerPage,e.paginationOptions.currentPage=e.defaultsPaginationOptions.currentPage,i.itemsPerPage&&(e.paginationOptions.itemsPerPage=i.itemsPerPage),i.page&&(!e.serverPagination&&(i.page-1)*e.paginationOptions.itemsPerPage>e.filtered.length?e.paginationOptions.currentPage=1:e.paginationOptions.currentPage=i.page),i.sort){var a=i.sort.split("-");e.sortOptions.predicate=decodeURIComponent(a[0]),e.sortOptions.direction=decodeURIComponent(a[1])}e.serverPagination||c()}function l(){var t=n.path().slice(1);!t&&e.sortOptions.predicate?e.sort(e.sortOptions.predicate,!0):e._gridOptions.getData("?"+t,function(t,i){e.filtered=t,e.paginationOptions.totalItems=i})}function c(){var t=Date.now(),i=!1;e._time={},e.sortOptions.predicate&&e.sortCache&&e.sortCache.predicate===e.sortOptions.predicate&&e.sortCache.direction===e.sortOptions.direction?(e.filtered=e.sortCache.data.slice(),i=!0):e.filtered=e._gridOptions.data.slice(),e._time.copy=Date.now()-t;var n=Date.now();p(),e._time.filters=Date.now()-n;var a=Date.now();e.sortOptions.predicate&&!i&&(e.filtered=r("orderBy")(e.filtered,e.sortOptions.predicate,"desc"===e.sortOptions.direction),e.sortCache={data:e.filtered.slice(),predicate:e.sortOptions.predicate,direction:e.sortOptions.direction}),e._time.sort=Date.now()-a,e._time.all=Date.now()-t,e.paginationOptions.totalItems=e.filtered.length}function p(){e.filters.forEach(function(t){var i=t.filterBy,r=t.model,n=t.isInScope?e.$eval(r):e.$parent.$eval(r),o=t.filterType;if(e.customFilters[r])e.filtered=e.customFilters[r](e.filtered,n,i);else if(n&&o){var s=a.getFilterByType(o);s&&(e.filtered=s(e.filtered,n,i))}})}e._gridOptions=e.$eval(i.attr("grid-options")),e._gridActions=e.$eval(i.attr("grid-actions")),e.serverPagination="true"===i.attr("server-pagination"),e.getDataDelay=i.attr("get-delay")||350,e._gridActions||(e.$parent.$eval(i.attr("grid-actions")+"= {}"),e._gridActions=e.$parent.$eval(i.attr("grid-actions"))),e._gridOptions.grid=e,e.filtered=e._gridOptions.data.slice(),e.paginationOptions=e._gridOptions.pagination?angular.copy(e._gridOptions.pagination):{},e.defaultsPaginationOptions={itemsPerPage:e.paginationOptions.itemsPerPage||"10",currentPage:e.paginationOptions.currentPage||1},e.paginationOptions=angular.copy(e.defaultsPaginationOptions),e.sortOptions=e._gridOptions.sort?angular.copy(e._gridOptions.sort):{},e.customFilters=e._gridOptions.customFilters?angular.copy(e._gridOptions.customFilters):{},e.urlSync=e._gridOptions.urlSync,e.$watch("_gridOptions.data",function(i){i&&i.length&&(e.sortCache={},e.filtered=e._gridOptions.data.slice(),e.filters.forEach(function(i){"select"===i.filterType&&(e[i.model+"Options"]=t(e.filtered,i.filterBy))}),e.urlSync?s(n.path()):c())}),e.sort=function(t,i){if(!i){var r=e.sortOptions.predicate===t&&"desc"===e.sortOptions.direction?"asc":"desc";e.sortOptions.direction=r,e.sortOptions.predicate=t}e.paginationOptions.currentPage=1,e.reloadGrid()},e.filter=function(){e.paginationOptions.currentPage=1,e.reloadGrid()},e.$on("$locationChangeSuccess",function(){(e.urlSync||e.serverPagination)&&(e.serverPagination&&(clearTimeout(e.getDataTimeout),e.getDataTimeout=setTimeout(l,e.getDataDelay)),e.filtered&&s(n.path()))}),e.reloadGrid=function(){e.urlSync||e.serverPagination?o():c()},e._gridActions.refresh=e.reloadGrid,e._gridActions.filter=e.filter,e._gridActions.sort=e.sort}]).directive("gridData",["$compile","$animate",function(e){return{restrict:"EA",scope:!0,controller:"gridController",link:function(i,r,n){var a=[],o=[],s=[],l=r.parent(),c=n.id,p="true"===n.serverPagination;angular.forEach(angular.element(l[0].querySelectorAll("[sortable]")),function(t){var r=angular.element(t),n=r.attr("sortable");a.push(r),r.attr("ng-class","{'sort-ascent' : sortOptions.predicate ==='"+n+"' && sortOptions.direction === 'asc', 'sort-descent' : sortOptions.predicate === '"+n+"' && sortOptions.direction === 'desc'}"),r.attr("ng-click","sort('"+n+"')"),e(r)(i)}),angular.forEach(angular.element(document.querySelectorAll("[filter-by]")),function(e){var n=angular.element(e),a=r.find(n).length>0,s=n.attr("filter-by"),l=n.attr("filter-type")||"",p=n.attr("ng-model"),d=n.attr("disable-url");c&&n.attr("grid-id")&&c!=n.attr("grid-id")||("select"!==l||(i[p+"Options"]=t(i.$eval(r.attr("grid-options")+".data"),s)),!~l.indexOf("date")||n.attr("ng-focus")||n.attr("ng-blur")||(n.attr("ng-focus","filter('{"+p+" : this."+p+"}')"),n.attr("ng-blur","filter('{"+p+" : this."+p+"}')")),p||(p=s,n.attr("ng-model",s),n.attr("ng-change","filter()")),o.push({model:p,isInScope:a,filterBy:s,filterType:l,disableUrl:d}))}),angular.forEach(angular.element(l[0].querySelectorAll("[grid-item]")),function(t){var r=angular.element(t);s.push(r),p?r.attr("ng-repeat","item in filtered"):r.attr("ng-repeat","item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage track by $index"),e(r)(i)}),i.sorting=a,i.rows=s,i.filters=o}}}]).factory("filtersFactory",function(){function t(t,e,i){return t.filter(function(t){return e&&t[i]?t[i]===e:!0})}function e(t,e,i){return t.filter(function(t){return e&&t[i]?~(t[i]+"").toLowerCase().indexOf((e+"").toLowerCase()):!!t[i]})}function i(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]<=e+86399999:!0})}function r(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]>=e:!0})}return{getFilterByType:function(n){switch(n){case"select":return t;case"text":return e;case"dateTo":return i;case"dateFrom":return r;default:return null}}}})}(); \ No newline at end of file diff --git a/src/js/dataGrid.js b/src/js/dataGrid.js index 8688c79..c85c4e4 100644 --- a/src/js/dataGrid.js +++ b/src/js/dataGrid.js @@ -185,11 +185,6 @@ } }); - if (!$scope.serverPagination) { - applyCustomFilters(); - } - - //pagination options $scope.paginationOptions.itemsPerPage = $scope.defaultsPaginationOptions.itemsPerPage; $scope.paginationOptions.currentPage = $scope.defaultsPaginationOptions.currentPage; From 33a81fc2ab4e0233a34ec31eda1def04c3fbdf74 Mon Sep 17 00:00:00 2001 From: skozlov Date: Wed, 6 Jul 2016 16:03:45 +0300 Subject: [PATCH 14/53] Fixed inintial request for server pagination, clear dates for material and some other minor fixes1 --- demo/bootstrap/css/loading-bar.min.css | 1 + demo/bootstrap/js/serverPaginationApp.js | 2 +- demo/bootstrap/server-pagination.html | 8 +- demo/material/css/loading-bar.min.css | 1 + demo/material/index.html | 2 +- dist/dataGrid.js | 11 +- dist/dataGrid.min.js | 2 +- dist/loading-bar.js | 324 +++++++++++++++++++++++ dist/loading-bar.min.js | 1 + src/js/dataGrid.js | 11 +- src/js/vendors/loading-bar.js | 324 +++++++++++++++++++++++ 11 files changed, 673 insertions(+), 14 deletions(-) create mode 100644 demo/bootstrap/css/loading-bar.min.css create mode 100644 demo/material/css/loading-bar.min.css create mode 100644 dist/loading-bar.js create mode 100644 dist/loading-bar.min.js create mode 100644 src/js/vendors/loading-bar.js diff --git a/demo/bootstrap/css/loading-bar.min.css b/demo/bootstrap/css/loading-bar.min.css new file mode 100644 index 0000000..db06f19 --- /dev/null +++ b/demo/bootstrap/css/loading-bar.min.css @@ -0,0 +1 @@ +#loading-bar,#loading-bar-spinner{-webkit-transition:350ms linear all;-moz-transition:350ms linear all;-o-transition:350ms linear all;transition:350ms linear all}#loading-bar .ng-enter,#loading-bar .ng-leave.ng-leave-active,#loading-bar-spinner .ng-enter,#loading-bar-spinner .ng-leave.ng-leave-active{opacity:0}#loading-bar .ng-enter.ng-enter-active,#loading-bar .ng-leave,#loading-bar-spinner .ng-enter.ng-enter-active,#loading-bar-spinner .ng-leave{opacity:1}#loading-bar{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.25);z-index:11002}#loading-bar .bar{-webkit-transition:width 350ms;-moz-transition:width 350ms;-o-transition:width 350ms;transition:width 350ms;background:#29d;position:fixed;z-index:11002;top:0;left:0;width:100%;height:2px;border-bottom-right-radius:1px;border-top-right-radius:1px}#loading-bar .peg{position:absolute;width:70px;right:0;top:0;height:2px}#loading-bar-spinner{display:block;position:fixed;z-index:11002;top:50%;left:50%;margin-left:-15px;margin-right:-15px}#loading-bar-spinner .spinner-icon{width:34px;height:34px;border:solid 2px transparent;border-top-color:#fff;border-left-color:#fff;-webkit-border-radius:17px;-moz-border-radius:17px;border-radius:17px;-webkit-animation:loading-bar-spinner .8s linear infinite;-moz-animation:loading-bar-spinner .8s linear infinite;-ms-animation:loading-bar-spinner .8s linear infinite;-o-animation:loading-bar-spinner .8s linear infinite;animation:loading-bar-spinner .8s linear infinite}@-webkit-keyframes loading-bar-spinner{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes loading-bar-spinner{0%{-moz-transform:rotate(0);transform:rotate(0)}100%{-moz-transform:rotate(360deg);transform:rotate(360deg)}}@-o-keyframes loading-bar-spinner{0%{-o-transform:rotate(0);transform:rotate(0)}100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@-ms-keyframes loading-bar-spinner{0%{-ms-transform:rotate(0);transform:rotate(0)}100%{-ms-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes loading-bar-spinner{0%{transform:rotate(0)}100%{transform:rotate(360deg)}} \ No newline at end of file diff --git a/demo/bootstrap/js/serverPaginationApp.js b/demo/bootstrap/js/serverPaginationApp.js index dc46500..c175e45 100644 --- a/demo/bootstrap/js/serverPaginationApp.js +++ b/demo/bootstrap/js/serverPaginationApp.js @@ -2,7 +2,7 @@ 'use strict'; angular - .module('myApp', ['ui.bootstrap', 'dataGrid', 'pagination']) + .module('myApp', ['ui.bootstrap', 'dataGrid', 'pagination', 'angular-loading-bar']) .controller('myAppController', MyAppController) .factory('myAppFactory', MyAppFactory); diff --git a/demo/bootstrap/server-pagination.html b/demo/bootstrap/server-pagination.html index f9b25a8..c3d5b73 100644 --- a/demo/bootstrap/server-pagination.html +++ b/demo/bootstrap/server-pagination.html @@ -23,6 +23,7 @@ +
    Order #Date PlacedStatusesTotalOrder #Date Placed + + Total
    - - + + - + @@ -218,5 +219,6 @@

    Angular Data Grid Server Pagination

    + \ No newline at end of file diff --git a/demo/material/css/loading-bar.min.css b/demo/material/css/loading-bar.min.css new file mode 100644 index 0000000..db06f19 --- /dev/null +++ b/demo/material/css/loading-bar.min.css @@ -0,0 +1 @@ +#loading-bar,#loading-bar-spinner{-webkit-transition:350ms linear all;-moz-transition:350ms linear all;-o-transition:350ms linear all;transition:350ms linear all}#loading-bar .ng-enter,#loading-bar .ng-leave.ng-leave-active,#loading-bar-spinner .ng-enter,#loading-bar-spinner .ng-leave.ng-leave-active{opacity:0}#loading-bar .ng-enter.ng-enter-active,#loading-bar .ng-leave,#loading-bar-spinner .ng-enter.ng-enter-active,#loading-bar-spinner .ng-leave{opacity:1}#loading-bar{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.25);z-index:11002}#loading-bar .bar{-webkit-transition:width 350ms;-moz-transition:width 350ms;-o-transition:width 350ms;transition:width 350ms;background:#29d;position:fixed;z-index:11002;top:0;left:0;width:100%;height:2px;border-bottom-right-radius:1px;border-top-right-radius:1px}#loading-bar .peg{position:absolute;width:70px;right:0;top:0;height:2px}#loading-bar-spinner{display:block;position:fixed;z-index:11002;top:50%;left:50%;margin-left:-15px;margin-right:-15px}#loading-bar-spinner .spinner-icon{width:34px;height:34px;border:solid 2px transparent;border-top-color:#fff;border-left-color:#fff;-webkit-border-radius:17px;-moz-border-radius:17px;border-radius:17px;-webkit-animation:loading-bar-spinner .8s linear infinite;-moz-animation:loading-bar-spinner .8s linear infinite;-ms-animation:loading-bar-spinner .8s linear infinite;-o-animation:loading-bar-spinner .8s linear infinite;animation:loading-bar-spinner .8s linear infinite}@-webkit-keyframes loading-bar-spinner{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes loading-bar-spinner{0%{-moz-transform:rotate(0);transform:rotate(0)}100%{-moz-transform:rotate(360deg);transform:rotate(360deg)}}@-o-keyframes loading-bar-spinner{0%{-o-transform:rotate(0);transform:rotate(0)}100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@-ms-keyframes loading-bar-spinner{0%{-ms-transform:rotate(0);transform:rotate(0)}100%{-ms-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes loading-bar-spinner{0%{transform:rotate(0)}100%{transform:rotate(360deg)}} \ No newline at end of file diff --git a/demo/material/index.html b/demo/material/index.html index cf9ec30..da5b4a1 100644 --- a/demo/material/index.html +++ b/demo/material/index.html @@ -79,7 +79,7 @@

    Angular Data Grid sample using Material Design styling

    ng-change="gridActions.filter()">
    - Clear Dates + Clear Dates
    diff --git a/dist/dataGrid.js b/dist/dataGrid.js index c85c4e4..8917d18 100644 --- a/dist/dataGrid.js +++ b/dist/dataGrid.js @@ -62,7 +62,7 @@ $scope.sortOptions.predicate = predicate; } $scope.paginationOptions.currentPage = 1; - $scope.reloadGrid(); + $scope.reloadGrid(isDefaultSort); }; $scope.filter = function () { @@ -82,9 +82,9 @@ } }); - $scope.reloadGrid = function () { + $scope.reloadGrid = function (isDefaultSort) { if ($scope.urlSync || $scope.serverPagination) { - changePath(); + changePath(isDefaultSort); } else { applyFilters(); } @@ -94,7 +94,7 @@ $scope._gridActions.filter = $scope.filter; $scope._gridActions.sort = $scope.sort; - function changePath() { + function changePath(isDefaultSort) { var path, needApplyFilters = false; path = 'page=' + $scope.paginationOptions.currentPage; @@ -135,6 +135,9 @@ applyFilters(); } $location.path(path); + if (isDefaultSort) { + $scope.$apply(); + } } function parseUrl() { diff --git a/dist/dataGrid.min.js b/dist/dataGrid.min.js index 31f08ff..82ad512 100644 --- a/dist/dataGrid.min.js +++ b/dist/dataGrid.min.js @@ -1 +1 @@ -!function(){"use strict";function t(t,e){var i=[];return t?(t.forEach(function(t){~i.indexOf(t[e])||i.push(t[e])}),i.map(function(t){return{text:t,value:t}})):void 0}angular.module("dataGrid",[]).filter("startFrom",function(){return function(t,e){return t?(e=+e,t.slice(e)):[]}}).controller("gridController",["$scope","$element","$filter","$location","filtersFactory",function(e,i,r,n,a){function o(){var t,i=!1;t="page="+e.paginationOptions.currentPage,e.paginationOptions.itemsPerPage!==e.defaultsPaginationOptions.itemsPerPage&&(t+="&itemsPerPage="+e.paginationOptions.itemsPerPage),e.sortOptions.predicate&&(t+="&sort="+encodeURIComponent(e.sortOptions.predicate+"-"+e.sortOptions.direction)),e.filters.forEach(function(r){var n=r.model,a=r.isInScope?e.$eval(n):e.$parent.$eval(n);if(r.disableUrl)return void(i=!0);if(a){var o;if(a instanceof Date){if(isNaN(a.getTime()))return;o=a.getFullYear()+"-",o+=a.getMonth()<9?"0"+(a.getMonth()+1)+"-":a.getMonth()+1+"-",o+=a.getDate()<10?"0"+a.getDate():a.getDate(),a=o}t+="&"+encodeURIComponent(n)+"="+encodeURIComponent(a)}}),i&&c(),n.path(t)}function s(){var t=n.path().slice(1),i={},r={};if(e.params=i,t.split("&").forEach(function(t){var e=t.split("=");i[e[0]]=e[1],"page"!==e[0]&&"sort"!==e[0]&&"itemsPerPage"!==e[0]&&(r[decodeURIComponent(e[0])]=decodeURIComponent(e[1]))}),e.filters.forEach(function(t){var i=t.model,n=r[i];if(!t.disableUrl){if(~t.filterType.toLowerCase().indexOf("date"))return e.$parent.__evaltmp=n?new Date(n):null,void e.$parent.$eval(i+"=__evaltmp");"select"!==t.filterType||n||(n=""),n&&(t.isInScope?(e.__evaltmp=n,e.$eval(i+"=__evaltmp")):(e.$parent.__evaltmp=n,e.$parent.$eval(i+"=__evaltmp")))}}),e.paginationOptions.itemsPerPage=e.defaultsPaginationOptions.itemsPerPage,e.paginationOptions.currentPage=e.defaultsPaginationOptions.currentPage,i.itemsPerPage&&(e.paginationOptions.itemsPerPage=i.itemsPerPage),i.page&&(!e.serverPagination&&(i.page-1)*e.paginationOptions.itemsPerPage>e.filtered.length?e.paginationOptions.currentPage=1:e.paginationOptions.currentPage=i.page),i.sort){var a=i.sort.split("-");e.sortOptions.predicate=decodeURIComponent(a[0]),e.sortOptions.direction=decodeURIComponent(a[1])}e.serverPagination||c()}function l(){var t=n.path().slice(1);!t&&e.sortOptions.predicate?e.sort(e.sortOptions.predicate,!0):e._gridOptions.getData("?"+t,function(t,i){e.filtered=t,e.paginationOptions.totalItems=i})}function c(){var t=Date.now(),i=!1;e._time={},e.sortOptions.predicate&&e.sortCache&&e.sortCache.predicate===e.sortOptions.predicate&&e.sortCache.direction===e.sortOptions.direction?(e.filtered=e.sortCache.data.slice(),i=!0):e.filtered=e._gridOptions.data.slice(),e._time.copy=Date.now()-t;var n=Date.now();p(),e._time.filters=Date.now()-n;var a=Date.now();e.sortOptions.predicate&&!i&&(e.filtered=r("orderBy")(e.filtered,e.sortOptions.predicate,"desc"===e.sortOptions.direction),e.sortCache={data:e.filtered.slice(),predicate:e.sortOptions.predicate,direction:e.sortOptions.direction}),e._time.sort=Date.now()-a,e._time.all=Date.now()-t,e.paginationOptions.totalItems=e.filtered.length}function p(){e.filters.forEach(function(t){var i=t.filterBy,r=t.model,n=t.isInScope?e.$eval(r):e.$parent.$eval(r),o=t.filterType;if(e.customFilters[r])e.filtered=e.customFilters[r](e.filtered,n,i);else if(n&&o){var s=a.getFilterByType(o);s&&(e.filtered=s(e.filtered,n,i))}})}e._gridOptions=e.$eval(i.attr("grid-options")),e._gridActions=e.$eval(i.attr("grid-actions")),e.serverPagination="true"===i.attr("server-pagination"),e.getDataDelay=i.attr("get-delay")||350,e._gridActions||(e.$parent.$eval(i.attr("grid-actions")+"= {}"),e._gridActions=e.$parent.$eval(i.attr("grid-actions"))),e._gridOptions.grid=e,e.filtered=e._gridOptions.data.slice(),e.paginationOptions=e._gridOptions.pagination?angular.copy(e._gridOptions.pagination):{},e.defaultsPaginationOptions={itemsPerPage:e.paginationOptions.itemsPerPage||"10",currentPage:e.paginationOptions.currentPage||1},e.paginationOptions=angular.copy(e.defaultsPaginationOptions),e.sortOptions=e._gridOptions.sort?angular.copy(e._gridOptions.sort):{},e.customFilters=e._gridOptions.customFilters?angular.copy(e._gridOptions.customFilters):{},e.urlSync=e._gridOptions.urlSync,e.$watch("_gridOptions.data",function(i){i&&i.length&&(e.sortCache={},e.filtered=e._gridOptions.data.slice(),e.filters.forEach(function(i){"select"===i.filterType&&(e[i.model+"Options"]=t(e.filtered,i.filterBy))}),e.urlSync?s(n.path()):c())}),e.sort=function(t,i){if(!i){var r=e.sortOptions.predicate===t&&"desc"===e.sortOptions.direction?"asc":"desc";e.sortOptions.direction=r,e.sortOptions.predicate=t}e.paginationOptions.currentPage=1,e.reloadGrid()},e.filter=function(){e.paginationOptions.currentPage=1,e.reloadGrid()},e.$on("$locationChangeSuccess",function(){(e.urlSync||e.serverPagination)&&(e.serverPagination&&(clearTimeout(e.getDataTimeout),e.getDataTimeout=setTimeout(l,e.getDataDelay)),e.filtered&&s(n.path()))}),e.reloadGrid=function(){e.urlSync||e.serverPagination?o():c()},e._gridActions.refresh=e.reloadGrid,e._gridActions.filter=e.filter,e._gridActions.sort=e.sort}]).directive("gridData",["$compile","$animate",function(e){return{restrict:"EA",scope:!0,controller:"gridController",link:function(i,r,n){var a=[],o=[],s=[],l=r.parent(),c=n.id,p="true"===n.serverPagination;angular.forEach(angular.element(l[0].querySelectorAll("[sortable]")),function(t){var r=angular.element(t),n=r.attr("sortable");a.push(r),r.attr("ng-class","{'sort-ascent' : sortOptions.predicate ==='"+n+"' && sortOptions.direction === 'asc', 'sort-descent' : sortOptions.predicate === '"+n+"' && sortOptions.direction === 'desc'}"),r.attr("ng-click","sort('"+n+"')"),e(r)(i)}),angular.forEach(angular.element(document.querySelectorAll("[filter-by]")),function(e){var n=angular.element(e),a=r.find(n).length>0,s=n.attr("filter-by"),l=n.attr("filter-type")||"",p=n.attr("ng-model"),d=n.attr("disable-url");c&&n.attr("grid-id")&&c!=n.attr("grid-id")||("select"!==l||(i[p+"Options"]=t(i.$eval(r.attr("grid-options")+".data"),s)),!~l.indexOf("date")||n.attr("ng-focus")||n.attr("ng-blur")||(n.attr("ng-focus","filter('{"+p+" : this."+p+"}')"),n.attr("ng-blur","filter('{"+p+" : this."+p+"}')")),p||(p=s,n.attr("ng-model",s),n.attr("ng-change","filter()")),o.push({model:p,isInScope:a,filterBy:s,filterType:l,disableUrl:d}))}),angular.forEach(angular.element(l[0].querySelectorAll("[grid-item]")),function(t){var r=angular.element(t);s.push(r),p?r.attr("ng-repeat","item in filtered"):r.attr("ng-repeat","item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage track by $index"),e(r)(i)}),i.sorting=a,i.rows=s,i.filters=o}}}]).factory("filtersFactory",function(){function t(t,e,i){return t.filter(function(t){return e&&t[i]?t[i]===e:!0})}function e(t,e,i){return t.filter(function(t){return e&&t[i]?~(t[i]+"").toLowerCase().indexOf((e+"").toLowerCase()):!!t[i]})}function i(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]<=e+86399999:!0})}function r(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]>=e:!0})}return{getFilterByType:function(n){switch(n){case"select":return t;case"text":return e;case"dateTo":return i;case"dateFrom":return r;default:return null}}}})}(); \ No newline at end of file +!function(){"use strict";function t(t,e){var i=[];return t?(t.forEach(function(t){~i.indexOf(t[e])||i.push(t[e])}),i.map(function(t){return{text:t,value:t}})):void 0}angular.module("dataGrid",[]).filter("startFrom",function(){return function(t,e){return t?(e=+e,t.slice(e)):[]}}).controller("gridController",["$scope","$element","$filter","$location","filtersFactory",function(e,i,r,n,a){function o(t){var i,r=!1;i="page="+e.paginationOptions.currentPage,e.paginationOptions.itemsPerPage!==e.defaultsPaginationOptions.itemsPerPage&&(i+="&itemsPerPage="+e.paginationOptions.itemsPerPage),e.sortOptions.predicate&&(i+="&sort="+encodeURIComponent(e.sortOptions.predicate+"-"+e.sortOptions.direction)),e.filters.forEach(function(t){var n=t.model,a=t.isInScope?e.$eval(n):e.$parent.$eval(n);if(t.disableUrl)return void(r=!0);if(a){var o;if(a instanceof Date){if(isNaN(a.getTime()))return;o=a.getFullYear()+"-",o+=a.getMonth()<9?"0"+(a.getMonth()+1)+"-":a.getMonth()+1+"-",o+=a.getDate()<10?"0"+a.getDate():a.getDate(),a=o}i+="&"+encodeURIComponent(n)+"="+encodeURIComponent(a)}}),r&&c(),n.path(i),t&&e.$apply()}function s(){var t=n.path().slice(1),i={},r={};if(e.params=i,t.split("&").forEach(function(t){var e=t.split("=");i[e[0]]=e[1],"page"!==e[0]&&"sort"!==e[0]&&"itemsPerPage"!==e[0]&&(r[decodeURIComponent(e[0])]=decodeURIComponent(e[1]))}),e.filters.forEach(function(t){var i=t.model,n=r[i];if(!t.disableUrl){if(~t.filterType.toLowerCase().indexOf("date"))return e.$parent.__evaltmp=n?new Date(n):null,void e.$parent.$eval(i+"=__evaltmp");"select"!==t.filterType||n||(n=""),n&&(t.isInScope?(e.__evaltmp=n,e.$eval(i+"=__evaltmp")):(e.$parent.__evaltmp=n,e.$parent.$eval(i+"=__evaltmp")))}}),e.paginationOptions.itemsPerPage=e.defaultsPaginationOptions.itemsPerPage,e.paginationOptions.currentPage=e.defaultsPaginationOptions.currentPage,i.itemsPerPage&&(e.paginationOptions.itemsPerPage=i.itemsPerPage),i.page&&(!e.serverPagination&&(i.page-1)*e.paginationOptions.itemsPerPage>e.filtered.length?e.paginationOptions.currentPage=1:e.paginationOptions.currentPage=i.page),i.sort){var a=i.sort.split("-");e.sortOptions.predicate=decodeURIComponent(a[0]),e.sortOptions.direction=decodeURIComponent(a[1])}e.serverPagination||c()}function l(){var t=n.path().slice(1);!t&&e.sortOptions.predicate?e.sort(e.sortOptions.predicate,!0):e._gridOptions.getData("?"+t,function(t,i){e.filtered=t,e.paginationOptions.totalItems=i})}function c(){var t=Date.now(),i=!1;e._time={},e.sortOptions.predicate&&e.sortCache&&e.sortCache.predicate===e.sortOptions.predicate&&e.sortCache.direction===e.sortOptions.direction?(e.filtered=e.sortCache.data.slice(),i=!0):e.filtered=e._gridOptions.data.slice(),e._time.copy=Date.now()-t;var n=Date.now();p(),e._time.filters=Date.now()-n;var a=Date.now();e.sortOptions.predicate&&!i&&(e.filtered=r("orderBy")(e.filtered,e.sortOptions.predicate,"desc"===e.sortOptions.direction),e.sortCache={data:e.filtered.slice(),predicate:e.sortOptions.predicate,direction:e.sortOptions.direction}),e._time.sort=Date.now()-a,e._time.all=Date.now()-t,e.paginationOptions.totalItems=e.filtered.length}function p(){e.filters.forEach(function(t){var i=t.filterBy,r=t.model,n=t.isInScope?e.$eval(r):e.$parent.$eval(r),o=t.filterType;if(e.customFilters[r])e.filtered=e.customFilters[r](e.filtered,n,i);else if(n&&o){var s=a.getFilterByType(o);s&&(e.filtered=s(e.filtered,n,i))}})}e._gridOptions=e.$eval(i.attr("grid-options")),e._gridActions=e.$eval(i.attr("grid-actions")),e.serverPagination="true"===i.attr("server-pagination"),e.getDataDelay=i.attr("get-delay")||350,e._gridActions||(e.$parent.$eval(i.attr("grid-actions")+"= {}"),e._gridActions=e.$parent.$eval(i.attr("grid-actions"))),e._gridOptions.grid=e,e.filtered=e._gridOptions.data.slice(),e.paginationOptions=e._gridOptions.pagination?angular.copy(e._gridOptions.pagination):{},e.defaultsPaginationOptions={itemsPerPage:e.paginationOptions.itemsPerPage||"10",currentPage:e.paginationOptions.currentPage||1},e.paginationOptions=angular.copy(e.defaultsPaginationOptions),e.sortOptions=e._gridOptions.sort?angular.copy(e._gridOptions.sort):{},e.customFilters=e._gridOptions.customFilters?angular.copy(e._gridOptions.customFilters):{},e.urlSync=e._gridOptions.urlSync,e.$watch("_gridOptions.data",function(i){i&&i.length&&(e.sortCache={},e.filtered=e._gridOptions.data.slice(),e.filters.forEach(function(i){"select"===i.filterType&&(e[i.model+"Options"]=t(e.filtered,i.filterBy))}),e.urlSync?s(n.path()):c())}),e.sort=function(t,i){if(!i){var r=e.sortOptions.predicate===t&&"desc"===e.sortOptions.direction?"asc":"desc";e.sortOptions.direction=r,e.sortOptions.predicate=t}e.paginationOptions.currentPage=1,e.reloadGrid(i)},e.filter=function(){e.paginationOptions.currentPage=1,e.reloadGrid()},e.$on("$locationChangeSuccess",function(){(e.urlSync||e.serverPagination)&&(e.serverPagination&&(clearTimeout(e.getDataTimeout),e.getDataTimeout=setTimeout(l,e.getDataDelay)),e.filtered&&s(n.path()))}),e.reloadGrid=function(t){e.urlSync||e.serverPagination?o(t):c()},e._gridActions.refresh=e.reloadGrid,e._gridActions.filter=e.filter,e._gridActions.sort=e.sort}]).directive("gridData",["$compile","$animate",function(e){return{restrict:"EA",scope:!0,controller:"gridController",link:function(i,r,n){var a=[],o=[],s=[],l=r.parent(),c=n.id,p="true"===n.serverPagination;angular.forEach(angular.element(l[0].querySelectorAll("[sortable]")),function(t){var r=angular.element(t),n=r.attr("sortable");a.push(r),r.attr("ng-class","{'sort-ascent' : sortOptions.predicate ==='"+n+"' && sortOptions.direction === 'asc', 'sort-descent' : sortOptions.predicate === '"+n+"' && sortOptions.direction === 'desc'}"),r.attr("ng-click","sort('"+n+"')"),e(r)(i)}),angular.forEach(angular.element(document.querySelectorAll("[filter-by]")),function(e){var n=angular.element(e),a=r.find(n).length>0,s=n.attr("filter-by"),l=n.attr("filter-type")||"",p=n.attr("ng-model"),d=n.attr("disable-url");c&&n.attr("grid-id")&&c!=n.attr("grid-id")||("select"!==l||(i[p+"Options"]=t(i.$eval(r.attr("grid-options")+".data"),s)),!~l.indexOf("date")||n.attr("ng-focus")||n.attr("ng-blur")||(n.attr("ng-focus","filter('{"+p+" : this."+p+"}')"),n.attr("ng-blur","filter('{"+p+" : this."+p+"}')")),p||(p=s,n.attr("ng-model",s),n.attr("ng-change","filter()")),o.push({model:p,isInScope:a,filterBy:s,filterType:l,disableUrl:d}))}),angular.forEach(angular.element(l[0].querySelectorAll("[grid-item]")),function(t){var r=angular.element(t);s.push(r),p?r.attr("ng-repeat","item in filtered"):r.attr("ng-repeat","item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage track by $index"),e(r)(i)}),i.sorting=a,i.rows=s,i.filters=o}}}]).factory("filtersFactory",function(){function t(t,e,i){return t.filter(function(t){return e&&t[i]?t[i]===e:!0})}function e(t,e,i){return t.filter(function(t){return e&&t[i]?~(t[i]+"").toLowerCase().indexOf((e+"").toLowerCase()):!!t[i]})}function i(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]<=e+86399999:!0})}function r(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]>=e:!0})}return{getFilterByType:function(n){switch(n){case"select":return t;case"text":return e;case"dateTo":return i;case"dateFrom":return r;default:return null}}}})}(); \ No newline at end of file diff --git a/dist/loading-bar.js b/dist/loading-bar.js new file mode 100644 index 0000000..d12341f --- /dev/null +++ b/dist/loading-bar.js @@ -0,0 +1,324 @@ +/*! + * angular-loading-bar v0.7.1 + * https://chieffancypants.github.io/angular-loading-bar + * Copyright (c) 2015 Wes Cruver + * License: MIT + */ +/* + * angular-loading-bar + * + * intercepts XHR requests and creates a loading bar. + * Based on the excellent nprogress work by rstacruz (more info in readme) + * + * (c) 2013 Wes Cruver + * License: MIT + */ + + +(function() { + + 'use strict'; + +// Alias the loading bar for various backwards compatibilities since the project has matured: + angular.module('angular-loading-bar', ['cfp.loadingBarInterceptor']); + angular.module('chieffancypants.loadingBar', ['cfp.loadingBarInterceptor']); + + + /** + * loadingBarInterceptor service + * + * Registers itself as an Angular interceptor and listens for XHR requests. + */ + angular.module('cfp.loadingBarInterceptor', ['cfp.loadingBar']) + .config(['$httpProvider', function ($httpProvider) { + + var interceptor = ['$q', '$cacheFactory', '$timeout', '$rootScope', '$log', 'cfpLoadingBar', function ($q, $cacheFactory, $timeout, $rootScope, $log, cfpLoadingBar) { + + /** + * The total number of requests made + */ + var reqsTotal = 0; + + /** + * The number of requests completed (either successfully or not) + */ + var reqsCompleted = 0; + + /** + * The amount of time spent fetching before showing the loading bar + */ + var latencyThreshold = cfpLoadingBar.latencyThreshold; + + /** + * $timeout handle for latencyThreshold + */ + var startTimeout; + + + /** + * calls cfpLoadingBar.complete() which removes the + * loading bar from the DOM. + */ + function setComplete() { + $timeout.cancel(startTimeout); + cfpLoadingBar.complete(); + reqsCompleted = 0; + reqsTotal = 0; + } + + /** + * Determine if the response has already been cached + * @param {Object} config the config option from the request + * @return {Boolean} retrns true if cached, otherwise false + */ + function isCached(config) { + var cache; + var defaultCache = $cacheFactory.get('$http'); + var defaults = $httpProvider.defaults; + + // Choose the proper cache source. Borrowed from angular: $http service + if ((config.cache || defaults.cache) && config.cache !== false && + (config.method === 'GET' || config.method === 'JSONP')) { + cache = angular.isObject(config.cache) ? config.cache + : angular.isObject(defaults.cache) ? defaults.cache + : defaultCache; + } + + var cached = cache !== undefined ? + cache.get(config.url) !== undefined : false; + + if (config.cached !== undefined && cached !== config.cached) { + return config.cached; + } + config.cached = cached; + return cached; + } + + + return { + 'request': function(config) { + // Check to make sure this request hasn't already been cached and that + // the requester didn't explicitly ask us to ignore this request: + if (!config.ignoreLoadingBar && !isCached(config)) { + $rootScope.$broadcast('cfpLoadingBar:loading', {url: config.url}); + if (reqsTotal === 0) { + startTimeout = $timeout(function() { + cfpLoadingBar.start(); + }, latencyThreshold); + } + reqsTotal++; + cfpLoadingBar.set(reqsCompleted / reqsTotal); + } + return config; + }, + + 'response': function(response) { + if (!response || !response.config) { + $log.error('Broken interceptor detected: Config object not supplied in response:\n https://github.com/chieffancypants/angular-loading-bar/pull/50'); + return response; + } + + if (!response.config.ignoreLoadingBar && !isCached(response.config)) { + reqsCompleted++; + $rootScope.$broadcast('cfpLoadingBar:loaded', {url: response.config.url, result: response}); + if (reqsCompleted >= reqsTotal) { + setComplete(); + } else { + cfpLoadingBar.set(reqsCompleted / reqsTotal); + } + } + return response; + }, + + 'responseError': function(rejection) { + if (!rejection || !rejection.config) { + $log.error('Broken interceptor detected: Config object not supplied in rejection:\n https://github.com/chieffancypants/angular-loading-bar/pull/50'); + return $q.reject(rejection); + } + + if (!rejection.config.ignoreLoadingBar && !isCached(rejection.config)) { + reqsCompleted++; + $rootScope.$broadcast('cfpLoadingBar:loaded', {url: rejection.config.url, result: rejection}); + if (reqsCompleted >= reqsTotal) { + setComplete(); + } else { + cfpLoadingBar.set(reqsCompleted / reqsTotal); + } + } + return $q.reject(rejection); + } + }; + }]; + + $httpProvider.interceptors.push(interceptor); + }]); + + + /** + * Loading Bar + * + * This service handles adding and removing the actual element in the DOM. + * Generally, best practices for DOM manipulation is to take place in a + * directive, but because the element itself is injected in the DOM only upon + * XHR requests, and it's likely needed on every view, the best option is to + * use a service. + */ + angular.module('cfp.loadingBar', []) + .provider('cfpLoadingBar', function() { + + this.includeSpinner = true; + this.includeBar = true; + this.latencyThreshold = 100; + this.startSize = 0.02; + this.parentSelector = 'body'; + this.spinnerTemplate = '
    '; + this.loadingBarTemplate = '
    '; + + this.$get = ['$injector', '$document', '$timeout', '$rootScope', function ($injector, $document, $timeout, $rootScope) { + var $animate; + var $parentSelector = this.parentSelector, + loadingBarContainer = angular.element(this.loadingBarTemplate), + loadingBar = loadingBarContainer.find('div').eq(0), + spinner = angular.element(this.spinnerTemplate); + + var incTimeout, + completeTimeout, + started = false, + status = 0; + + var includeSpinner = this.includeSpinner; + var includeBar = this.includeBar; + var startSize = this.startSize; + + /** + * Inserts the loading bar element into the dom, and sets it to 2% + */ + function _start() { + if (!$animate) { + $animate = $injector.get('$animate'); + } + + var $parent = $document.find($parentSelector).eq(0); + $timeout.cancel(completeTimeout); + + // do not continually broadcast the started event: + if (started) { + return; + } + + $rootScope.$broadcast('cfpLoadingBar:started'); + started = true; + + if (includeBar) { + $animate.enter(loadingBarContainer, $parent, angular.element($parent[0].lastChild)); + } + + if (includeSpinner) { + $animate.enter(spinner, $parent, angular.element($parent[0].lastChild)); + } + + _set(startSize); + } + + /** + * Set the loading bar's width to a certain percent. + * + * @param n any value between 0 and 1 + */ + function _set(n) { + if (!started) { + return; + } + var pct = (n * 100) + '%'; + loadingBar.css('width', pct); + status = n; + + // increment loadingbar to give the illusion that there is always + // progress but make sure to cancel the previous timeouts so we don't + // have multiple incs running at the same time. + $timeout.cancel(incTimeout); + incTimeout = $timeout(function() { + _inc(); + }, 250); + } + + /** + * Increments the loading bar by a random amount + * but slows down as it progresses + */ + function _inc() { + if (_status() >= 1) { + return; + } + + var rnd = 0; + + // TODO: do this mathmatically instead of through conditions + + var stat = _status(); + if (stat >= 0 && stat < 0.25) { + // Start out between 3 - 6% increments + rnd = (Math.random() * (5 - 3 + 1) + 3) / 100; + } else if (stat >= 0.25 && stat < 0.65) { + // increment between 0 - 3% + rnd = (Math.random() * 3) / 100; + } else if (stat >= 0.65 && stat < 0.9) { + // increment between 0 - 2% + rnd = (Math.random() * 2) / 100; + } else if (stat >= 0.9 && stat < 0.99) { + // finally, increment it .5 % + rnd = 0.005; + } else { + // after 99%, don't increment: + rnd = 0; + } + + var pct = _status() + rnd; + _set(pct); + } + + function _status() { + return status; + } + + function _completeAnimation() { + status = 0; + started = false; + } + + function _complete() { + if (!$animate) { + $animate = $injector.get('$animate'); + } + + $rootScope.$broadcast('cfpLoadingBar:completed'); + _set(1); + + $timeout.cancel(completeTimeout); + + // Attempt to aggregate any start/complete calls within 500ms: + completeTimeout = $timeout(function() { + var promise = $animate.leave(loadingBarContainer, _completeAnimation); + if (promise && promise.then) { + promise.then(_completeAnimation); + } + $animate.leave(spinner); + }, 500); + } + + return { + start : _start, + set : _set, + status : _status, + inc : _inc, + complete : _complete, + includeSpinner : this.includeSpinner, + latencyThreshold : this.latencyThreshold, + parentSelector : this.parentSelector, + startSize : this.startSize + }; + + + }]; // + }); // wtf javascript. srsly +})(); // \ No newline at end of file diff --git a/dist/loading-bar.min.js b/dist/loading-bar.min.js new file mode 100644 index 0000000..f0fdc27 --- /dev/null +++ b/dist/loading-bar.min.js @@ -0,0 +1 @@ +!function(){"use strict";angular.module("angular-loading-bar",["cfp.loadingBarInterceptor"]),angular.module("chieffancypants.loadingBar",["cfp.loadingBarInterceptor"]),angular.module("cfp.loadingBarInterceptor",["cfp.loadingBar"]).config(["$httpProvider",function(e){var n=["$q","$cacheFactory","$timeout","$rootScope","$log","cfpLoadingBar",function(n,t,a,r,i,c){function o(){a.cancel(d),c.complete(),u=0,s=0}function l(n){var a,r=t.get("$http"),i=e.defaults;!n.cache&&!i.cache||n.cache===!1||"GET"!==n.method&&"JSONP"!==n.method||(a=angular.isObject(n.cache)?n.cache:angular.isObject(i.cache)?i.cache:r);var c=void 0!==a?void 0!==a.get(n.url):!1;return void 0!==n.cached&&c!==n.cached?n.cached:(n.cached=c,c)}var d,s=0,u=0,g=c.latencyThreshold;return{request:function(e){return e.ignoreLoadingBar||l(e)||(r.$broadcast("cfpLoadingBar:loading",{url:e.url}),0===s&&(d=a(function(){c.start()},g)),s++,c.set(u/s)),e},response:function(e){return e&&e.config?(e.config.ignoreLoadingBar||l(e.config)||(u++,r.$broadcast("cfpLoadingBar:loaded",{url:e.config.url,result:e}),u>=s?o():c.set(u/s)),e):(i.error("Broken interceptor detected: Config object not supplied in response:\n https://github.com/chieffancypants/angular-loading-bar/pull/50"),e)},responseError:function(e){return e&&e.config?(e.config.ignoreLoadingBar||l(e.config)||(u++,r.$broadcast("cfpLoadingBar:loaded",{url:e.config.url,result:e}),u>=s?o():c.set(u/s)),n.reject(e)):(i.error("Broken interceptor detected: Config object not supplied in rejection:\n https://github.com/chieffancypants/angular-loading-bar/pull/50"),n.reject(e))}}}];e.interceptors.push(n)}]),angular.module("cfp.loadingBar",[]).provider("cfpLoadingBar",function(){this.includeSpinner=!0,this.includeBar=!0,this.latencyThreshold=100,this.startSize=.02,this.parentSelector="body",this.spinnerTemplate='
    ',this.loadingBarTemplate='
    ',this.$get=["$injector","$document","$timeout","$rootScope",function(e,n,t,a){function r(){s||(s=e.get("$animate"));var r=n.find(h).eq(0);t.cancel(g),m||(a.$broadcast("cfpLoadingBar:started"),m=!0,b&&s.enter(p,r,angular.element(r[0].lastChild)),$&&s.enter(v,r,angular.element(r[0].lastChild)),i(S))}function i(e){if(m){var n=100*e+"%";f.css("width",n),B=e,t.cancel(u),u=t(function(){c()},250)}}function c(){if(!(o()>=1)){var e=0,n=o();e=n>=0&&.25>n?(3*Math.random()+3)/100:n>=.25&&.65>n?3*Math.random()/100:n>=.65&&.9>n?2*Math.random()/100:n>=.9&&.99>n?.005:0;var t=o()+e;i(t)}}function o(){return B}function l(){B=0,m=!1}function d(){s||(s=e.get("$animate")),a.$broadcast("cfpLoadingBar:completed"),i(1),t.cancel(g),g=t(function(){var e=s.leave(p,l);e&&e.then&&e.then(l),s.leave(v)},500)}var s,u,g,h=this.parentSelector,p=angular.element(this.loadingBarTemplate),f=p.find("div").eq(0),v=angular.element(this.spinnerTemplate),m=!1,B=0,$=this.includeSpinner,b=this.includeBar,S=this.startSize;return{start:r,set:i,status:o,inc:c,complete:d,includeSpinner:this.includeSpinner,latencyThreshold:this.latencyThreshold,parentSelector:this.parentSelector,startSize:this.startSize}}]})}(); \ No newline at end of file diff --git a/src/js/dataGrid.js b/src/js/dataGrid.js index c85c4e4..8917d18 100644 --- a/src/js/dataGrid.js +++ b/src/js/dataGrid.js @@ -62,7 +62,7 @@ $scope.sortOptions.predicate = predicate; } $scope.paginationOptions.currentPage = 1; - $scope.reloadGrid(); + $scope.reloadGrid(isDefaultSort); }; $scope.filter = function () { @@ -82,9 +82,9 @@ } }); - $scope.reloadGrid = function () { + $scope.reloadGrid = function (isDefaultSort) { if ($scope.urlSync || $scope.serverPagination) { - changePath(); + changePath(isDefaultSort); } else { applyFilters(); } @@ -94,7 +94,7 @@ $scope._gridActions.filter = $scope.filter; $scope._gridActions.sort = $scope.sort; - function changePath() { + function changePath(isDefaultSort) { var path, needApplyFilters = false; path = 'page=' + $scope.paginationOptions.currentPage; @@ -135,6 +135,9 @@ applyFilters(); } $location.path(path); + if (isDefaultSort) { + $scope.$apply(); + } } function parseUrl() { diff --git a/src/js/vendors/loading-bar.js b/src/js/vendors/loading-bar.js new file mode 100644 index 0000000..d12341f --- /dev/null +++ b/src/js/vendors/loading-bar.js @@ -0,0 +1,324 @@ +/*! + * angular-loading-bar v0.7.1 + * https://chieffancypants.github.io/angular-loading-bar + * Copyright (c) 2015 Wes Cruver + * License: MIT + */ +/* + * angular-loading-bar + * + * intercepts XHR requests and creates a loading bar. + * Based on the excellent nprogress work by rstacruz (more info in readme) + * + * (c) 2013 Wes Cruver + * License: MIT + */ + + +(function() { + + 'use strict'; + +// Alias the loading bar for various backwards compatibilities since the project has matured: + angular.module('angular-loading-bar', ['cfp.loadingBarInterceptor']); + angular.module('chieffancypants.loadingBar', ['cfp.loadingBarInterceptor']); + + + /** + * loadingBarInterceptor service + * + * Registers itself as an Angular interceptor and listens for XHR requests. + */ + angular.module('cfp.loadingBarInterceptor', ['cfp.loadingBar']) + .config(['$httpProvider', function ($httpProvider) { + + var interceptor = ['$q', '$cacheFactory', '$timeout', '$rootScope', '$log', 'cfpLoadingBar', function ($q, $cacheFactory, $timeout, $rootScope, $log, cfpLoadingBar) { + + /** + * The total number of requests made + */ + var reqsTotal = 0; + + /** + * The number of requests completed (either successfully or not) + */ + var reqsCompleted = 0; + + /** + * The amount of time spent fetching before showing the loading bar + */ + var latencyThreshold = cfpLoadingBar.latencyThreshold; + + /** + * $timeout handle for latencyThreshold + */ + var startTimeout; + + + /** + * calls cfpLoadingBar.complete() which removes the + * loading bar from the DOM. + */ + function setComplete() { + $timeout.cancel(startTimeout); + cfpLoadingBar.complete(); + reqsCompleted = 0; + reqsTotal = 0; + } + + /** + * Determine if the response has already been cached + * @param {Object} config the config option from the request + * @return {Boolean} retrns true if cached, otherwise false + */ + function isCached(config) { + var cache; + var defaultCache = $cacheFactory.get('$http'); + var defaults = $httpProvider.defaults; + + // Choose the proper cache source. Borrowed from angular: $http service + if ((config.cache || defaults.cache) && config.cache !== false && + (config.method === 'GET' || config.method === 'JSONP')) { + cache = angular.isObject(config.cache) ? config.cache + : angular.isObject(defaults.cache) ? defaults.cache + : defaultCache; + } + + var cached = cache !== undefined ? + cache.get(config.url) !== undefined : false; + + if (config.cached !== undefined && cached !== config.cached) { + return config.cached; + } + config.cached = cached; + return cached; + } + + + return { + 'request': function(config) { + // Check to make sure this request hasn't already been cached and that + // the requester didn't explicitly ask us to ignore this request: + if (!config.ignoreLoadingBar && !isCached(config)) { + $rootScope.$broadcast('cfpLoadingBar:loading', {url: config.url}); + if (reqsTotal === 0) { + startTimeout = $timeout(function() { + cfpLoadingBar.start(); + }, latencyThreshold); + } + reqsTotal++; + cfpLoadingBar.set(reqsCompleted / reqsTotal); + } + return config; + }, + + 'response': function(response) { + if (!response || !response.config) { + $log.error('Broken interceptor detected: Config object not supplied in response:\n https://github.com/chieffancypants/angular-loading-bar/pull/50'); + return response; + } + + if (!response.config.ignoreLoadingBar && !isCached(response.config)) { + reqsCompleted++; + $rootScope.$broadcast('cfpLoadingBar:loaded', {url: response.config.url, result: response}); + if (reqsCompleted >= reqsTotal) { + setComplete(); + } else { + cfpLoadingBar.set(reqsCompleted / reqsTotal); + } + } + return response; + }, + + 'responseError': function(rejection) { + if (!rejection || !rejection.config) { + $log.error('Broken interceptor detected: Config object not supplied in rejection:\n https://github.com/chieffancypants/angular-loading-bar/pull/50'); + return $q.reject(rejection); + } + + if (!rejection.config.ignoreLoadingBar && !isCached(rejection.config)) { + reqsCompleted++; + $rootScope.$broadcast('cfpLoadingBar:loaded', {url: rejection.config.url, result: rejection}); + if (reqsCompleted >= reqsTotal) { + setComplete(); + } else { + cfpLoadingBar.set(reqsCompleted / reqsTotal); + } + } + return $q.reject(rejection); + } + }; + }]; + + $httpProvider.interceptors.push(interceptor); + }]); + + + /** + * Loading Bar + * + * This service handles adding and removing the actual element in the DOM. + * Generally, best practices for DOM manipulation is to take place in a + * directive, but because the element itself is injected in the DOM only upon + * XHR requests, and it's likely needed on every view, the best option is to + * use a service. + */ + angular.module('cfp.loadingBar', []) + .provider('cfpLoadingBar', function() { + + this.includeSpinner = true; + this.includeBar = true; + this.latencyThreshold = 100; + this.startSize = 0.02; + this.parentSelector = 'body'; + this.spinnerTemplate = '
    '; + this.loadingBarTemplate = '
    '; + + this.$get = ['$injector', '$document', '$timeout', '$rootScope', function ($injector, $document, $timeout, $rootScope) { + var $animate; + var $parentSelector = this.parentSelector, + loadingBarContainer = angular.element(this.loadingBarTemplate), + loadingBar = loadingBarContainer.find('div').eq(0), + spinner = angular.element(this.spinnerTemplate); + + var incTimeout, + completeTimeout, + started = false, + status = 0; + + var includeSpinner = this.includeSpinner; + var includeBar = this.includeBar; + var startSize = this.startSize; + + /** + * Inserts the loading bar element into the dom, and sets it to 2% + */ + function _start() { + if (!$animate) { + $animate = $injector.get('$animate'); + } + + var $parent = $document.find($parentSelector).eq(0); + $timeout.cancel(completeTimeout); + + // do not continually broadcast the started event: + if (started) { + return; + } + + $rootScope.$broadcast('cfpLoadingBar:started'); + started = true; + + if (includeBar) { + $animate.enter(loadingBarContainer, $parent, angular.element($parent[0].lastChild)); + } + + if (includeSpinner) { + $animate.enter(spinner, $parent, angular.element($parent[0].lastChild)); + } + + _set(startSize); + } + + /** + * Set the loading bar's width to a certain percent. + * + * @param n any value between 0 and 1 + */ + function _set(n) { + if (!started) { + return; + } + var pct = (n * 100) + '%'; + loadingBar.css('width', pct); + status = n; + + // increment loadingbar to give the illusion that there is always + // progress but make sure to cancel the previous timeouts so we don't + // have multiple incs running at the same time. + $timeout.cancel(incTimeout); + incTimeout = $timeout(function() { + _inc(); + }, 250); + } + + /** + * Increments the loading bar by a random amount + * but slows down as it progresses + */ + function _inc() { + if (_status() >= 1) { + return; + } + + var rnd = 0; + + // TODO: do this mathmatically instead of through conditions + + var stat = _status(); + if (stat >= 0 && stat < 0.25) { + // Start out between 3 - 6% increments + rnd = (Math.random() * (5 - 3 + 1) + 3) / 100; + } else if (stat >= 0.25 && stat < 0.65) { + // increment between 0 - 3% + rnd = (Math.random() * 3) / 100; + } else if (stat >= 0.65 && stat < 0.9) { + // increment between 0 - 2% + rnd = (Math.random() * 2) / 100; + } else if (stat >= 0.9 && stat < 0.99) { + // finally, increment it .5 % + rnd = 0.005; + } else { + // after 99%, don't increment: + rnd = 0; + } + + var pct = _status() + rnd; + _set(pct); + } + + function _status() { + return status; + } + + function _completeAnimation() { + status = 0; + started = false; + } + + function _complete() { + if (!$animate) { + $animate = $injector.get('$animate'); + } + + $rootScope.$broadcast('cfpLoadingBar:completed'); + _set(1); + + $timeout.cancel(completeTimeout); + + // Attempt to aggregate any start/complete calls within 500ms: + completeTimeout = $timeout(function() { + var promise = $animate.leave(loadingBarContainer, _completeAnimation); + if (promise && promise.then) { + promise.then(_completeAnimation); + } + $animate.leave(spinner); + }, 500); + } + + return { + start : _start, + set : _set, + status : _status, + inc : _inc, + complete : _complete, + includeSpinner : this.includeSpinner, + latencyThreshold : this.latencyThreshold, + parentSelector : this.parentSelector, + startSize : this.startSize + }; + + + }]; // + }); // wtf javascript. srsly +})(); // \ No newline at end of file From e60dabaa3652ea1b2aeebbb00bf3826006ca4664 Mon Sep 17 00:00:00 2001 From: skozlov Date: Thu, 9 Mar 2017 14:29:56 +0300 Subject: [PATCH 15/53] Fixed problem when grid-item contains directive with ng-transclude in template. --- demo/100k/index.html | 12 ++++---- demo/bootstrap/index.html | 12 ++++---- demo/bootstrap/js/serverPaginationApp.js | 8 +++--- demo/bootstrap/multiple.html | 12 ++++---- demo/bootstrap/server-pagination.html | 10 +++---- demo/material/index.html | 8 +++--- dist/dataGrid.js | 36 +++++++++++++----------- dist/dataGrid.min.js | 2 +- src/js/dataGrid.js | 36 +++++++++++++----------- 9 files changed, 70 insertions(+), 66 deletions(-) diff --git a/demo/100k/index.html b/demo/100k/index.html index d16ea35..4ce1f28 100644 --- a/demo/100k/index.html +++ b/demo/100k/index.html @@ -207,14 +207,14 @@

    Angular Data Grid 100k Example

    - - - - - + + + + + - + \ No newline at end of file diff --git a/demo/bootstrap/index.html b/demo/bootstrap/index.html index 90b9860..8329619 100644 --- a/demo/bootstrap/index.html +++ b/demo/bootstrap/index.html @@ -16,7 +16,7 @@ -
      +
    Order #Date PlacedOrder # Date Placed TotalTotal
    ` layout to any `
    ` structure. - Easily switch between the most popular Bootstrap and Google Material theming, or apply your own CSS theme just by changing several CSS classes. - Built-in sync with browser address bar (URL), so you can copy-n-paste sorting/filtering/pagination results URL and open it in other browser / send to anyone - even if pagination / filtering are done on a client-side. + - Support of [Angular UI Router](https://github.com/angular-ui/ui-router) navigation. - Unlike most part of other Angular DataGrids, we intentionally use non-isolated scope of the directive to maximize flexibility, so it can be easily synchronized with any data changes inside your controller. NOTE! With great power comes great responsibility, so use non-isolated API wisely. From 419d9556f9851161f3e43ddee5d3ecb4e9f33b8a Mon Sep 17 00:00:00 2001 From: skozlov Date: Tue, 28 Mar 2017 14:07:49 +0300 Subject: [PATCH 24/53] UI Router plus server pagination - fixed #20 --- demo/bootstrap/index.html | 3 + .../bootstrap/js/routerServerPaginationApp.js | 60 ++++++ demo/bootstrap/ui-router.html | 54 ++++++ .../views/router-server-pagination.html | 174 ++++++++++++++++++ dist/dataGrid.js | 53 +++--- dist/dataGrid.min.js | 2 +- src/js/dataGrid.js | 53 +++--- 7 files changed, 352 insertions(+), 47 deletions(-) create mode 100644 demo/bootstrap/js/routerServerPaginationApp.js create mode 100644 demo/bootstrap/ui-router.html create mode 100644 demo/bootstrap/views/router-server-pagination.html diff --git a/demo/bootstrap/index.html b/demo/bootstrap/index.html index 8329619..b0919de 100644 --- a/demo/bootstrap/index.html +++ b/demo/bootstrap/index.html @@ -45,6 +45,9 @@

    Additional Demos

  • Server pagination
  • +
  • + UI Router plus server pagination +

  • diff --git a/demo/bootstrap/js/routerServerPaginationApp.js b/demo/bootstrap/js/routerServerPaginationApp.js new file mode 100644 index 0000000..e8b28a8 --- /dev/null +++ b/demo/bootstrap/js/routerServerPaginationApp.js @@ -0,0 +1,60 @@ +(function () { + 'use strict'; + + angular + .module('myApp', ['ui.bootstrap', 'dataGrid', 'pagination', 'ui.router', 'angular-loading-bar']) + .config(config) + .factory('myAppFactory', MyAppFactory); + + config.$inject = ['$stateProvider', '$urlRouterProvider', '$locationProvider']; + MyAppController.$inject = ['$scope', 'myAppFactory', '$state']; + MyAppFactory.$inject = ['$http']; + + + function config($stateProvider, $urlRouterProvider, $locationProvider) { + //$locationProvider.html5Mode(true); + + $urlRouterProvider.otherwise('/orders'); + + $stateProvider + .state('orders', { + url: '/orders', + templateUrl: 'views/router-server-pagination.html', + controller: MyAppController + }) + } + + function MyAppController($scope, myAppFactory, $state) { + + $scope.gridOptions = { + data: [], + getData: myAppFactory.getOrdersData, + sort: { + predicate: 'orderNo', + direction: 'asc' + } + }; + $scope.gridActions = {}; + myAppFactory.getStatuses().then(function (resp) { + $scope.UI.statusOptions = resp.data; + }) + } + + function MyAppFactory($http) { + var herokuDomain = 'https://server-pagination.herokuapp.com'; + return { + getOrdersData: getOrdersData, + getStatuses: getStatuses + }; + + function getOrdersData(params, callback) { + $http.get(herokuDomain + '/orders' + params).then(function (response) { + callback(response.data.orders, response.data.ordersCount); + }); + } + + function getStatuses() { + return $http.get(herokuDomain + '/orders/statuses'); + } + } +})(); diff --git a/demo/bootstrap/ui-router.html b/demo/bootstrap/ui-router.html new file mode 100644 index 0000000..139b239 --- /dev/null +++ b/demo/bootstrap/ui-router.html @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/bootstrap/views/router-server-pagination.html b/demo/bootstrap/views/router-server-pagination.html new file mode 100644 index 0000000..d916b5f --- /dev/null +++ b/demo/bootstrap/views/router-server-pagination.html @@ -0,0 +1,174 @@ +
    +
    +

    Angular Data Grid - UI Router Server Pagination.

    + UI Router plus all features for server pagination
    + Features enabled: sorting, filtering (using both in-grid and external controls), pagination and items-per-page functionality. + Angular UI Datepicker used for date controls, although you can use any other framework, plugin or styling. + Project GitHub +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    + + + + +
    +
    +
    +
    +
    + + +
    + + + + +
    +
    + +
    +
    +
    + + +
    +
    +
    {{paginationOptions.totalItems}} items total
    +
    +
    +
    +
    +
    +
    +
    + + +
    + +
    +
    + +
    + + + + + + + + + + + + + + + + +
    Order #Date Placed + + Total
    {{item.orderNo}}{{item.datePlaced | date:'MM/dd/yyyy'}}{{item.status}}{{item.total}}
    +
    +
    {{paginationOptions.totalItems}} items total
    +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/dist/dataGrid.js b/dist/dataGrid.js index 1bc8aef..1ae356c 100644 --- a/dist/dataGrid.js +++ b/dist/dataGrid.js @@ -48,7 +48,7 @@ }); if ($scope.urlSync) { - parseUrl($location.path()); + parseUrl(); } else { applyFilters(); } @@ -71,15 +71,11 @@ }; $scope.$on('$locationChangeSuccess', function () { - if ($scope.urlSync || $scope.serverPagination) { - if ($scope.serverPagination) { - clearTimeout($scope.getDataTimeout); - $scope.getDataTimeout = setTimeout(getData, $scope.getDataDelay); - } - if ($scope.filtered) { - parseUrl($location.path()); - } - } + onChangeStateOrLocation() + }); + + $scope.$on("$stateChangeSuccess", function (event, toState) { + onChangeStateOrLocation() }); $scope.reloadGrid = function (isDefaultSort) { @@ -94,6 +90,18 @@ $scope._gridActions.filter = $scope.filter; $scope._gridActions.sort = $scope.sort; + function onChangeStateOrLocation(){ + if ($scope.urlSync || $scope.serverPagination) { + if ($scope.serverPagination) { + clearTimeout($scope.getDataTimeout); + $scope.getDataTimeout = setTimeout(getData, $scope.getDataDelay); + } + if ($scope.filtered) { + parseUrl(); + } + } + } + function changePath(isDefaultSort) { var path, needApplyFilters = false; @@ -134,27 +142,21 @@ if (needApplyFilters) { applyFilters(); } - $location.path(path); + $location.search(path); if (isDefaultSort) { $scope.$apply(); } } function parseUrl() { - var url = $location.path().slice(1), - params = {}, + var params = $location.search(), customParams = {}; - $scope.params = params; - - url.split('&').forEach(function (urlParam) { - var param = urlParam.split('='); - params[param[0]] = param[1]; - if (param[0] !== 'page' && param[0] !== 'sort' && param[0] !== 'itemsPerPage') { - customParams[decodeURIComponent(param[0])] = decodeURIComponent(param[1]); - } + Object.keys(params).forEach(function(key) { + if (key !== 'page' && key !== 'sort' && key !== 'itemsPerPage') { + customParams[key] = params[key]; } - ); + }); //custom filters $scope.filters.forEach(function (filter) { @@ -216,7 +218,12 @@ } function getData() { - var url = $location.path().slice(1); + var url = ''; + var params = $location.search(); + Object.keys(params).forEach(function(key) { + url += key + '=' + params[key] + '&'; + }); + url = url.slice(0, -1); if (!url && $scope.sortOptions.predicate) { $scope.sort($scope.sortOptions.predicate, true); } else { diff --git a/dist/dataGrid.min.js b/dist/dataGrid.min.js index 9bf1cd2..c0ba104 100644 --- a/dist/dataGrid.min.js +++ b/dist/dataGrid.min.js @@ -1 +1 @@ -!function(){"use strict";function t(t,e){var i=[];if(t)return t.forEach(function(t){~i.indexOf(t[e])||i.push(t[e])}),i.map(function(t){return{text:t,value:t}})}angular.module("dataGrid",[]).filter("startFrom",function(){return function(t,e){return t?(e=+e,t.slice(e)):[]}}).controller("gridController",["$scope","$element","$filter","$location","filtersFactory",function(e,i,r,n,a){function o(t){var i,r=!1;i="page="+e.paginationOptions.currentPage,e.paginationOptions.itemsPerPage!==e.defaultsPaginationOptions.itemsPerPage&&(i+="&itemsPerPage="+e.paginationOptions.itemsPerPage),e.sortOptions.predicate&&(i+="&sort="+encodeURIComponent(e.sortOptions.predicate+"-"+e.sortOptions.direction)),e.filters.forEach(function(t){var n=t.model,a=t.isInScope?e.$eval(n):e.$parent.$eval(n);if(t.disableUrl)return void(r=!0);if(a){var o;if(a instanceof Date){if(isNaN(a.getTime()))return;o=a.getFullYear()+"-",o+=a.getMonth()<9?"0"+(a.getMonth()+1)+"-":a.getMonth()+1+"-",o+=a.getDate()<10?"0"+a.getDate():a.getDate(),a=o}i+="&"+encodeURIComponent(n)+"="+encodeURIComponent(a)}}),r&&c(),n.path(i),t&&e.$apply()}function s(){var t=n.path().slice(1),i={},r={};if(e.params=i,t.split("&").forEach(function(t){var e=t.split("=");i[e[0]]=e[1],"page"!==e[0]&&"sort"!==e[0]&&"itemsPerPage"!==e[0]&&(r[decodeURIComponent(e[0])]=decodeURIComponent(e[1]))}),e.filters.forEach(function(t){var i=t.model,n=r[i];if(!t.disableUrl){if(~t.filterType.toLowerCase().indexOf("date"))return e.$parent.__evaltmp=n?new Date(n):null,void e.$parent.$eval(i+"=__evaltmp");"select"!==t.filterType||n||(n=""),n&&(t.isInScope?(e.__evaltmp=n,e.$eval(i+"=__evaltmp")):(e.$parent.__evaltmp=n,e.$parent.$eval(i+"=__evaltmp")))}}),e.paginationOptions.itemsPerPage=e.defaultsPaginationOptions.itemsPerPage,e.paginationOptions.currentPage=e.defaultsPaginationOptions.currentPage,i.itemsPerPage&&(e.paginationOptions.itemsPerPage=i.itemsPerPage),i.page&&(!e.serverPagination&&(i.page-1)*e.paginationOptions.itemsPerPage>e.filtered.length?e.paginationOptions.currentPage=1:e.paginationOptions.currentPage=i.page),i.sort){var a=i.sort.split("-");e.sortOptions.predicate=decodeURIComponent(a[0]),e.sortOptions.direction=decodeURIComponent(a[1])}e.serverPagination||c()}function l(){var t=n.path().slice(1);!t&&e.sortOptions.predicate?e.sort(e.sortOptions.predicate,!0):e._gridOptions.getData("?"+t,function(t,i){e.filtered=t,e.paginationOptions.totalItems=i})}function c(){var t=Date.now(),i=!1;e._time={},e.sortOptions.predicate&&e.sortCache&&e.sortCache.predicate===e.sortOptions.predicate&&e.sortCache.direction===e.sortOptions.direction?(e.filtered=e.sortCache.data.slice(),i=!0):e.filtered=e._gridOptions.data.slice(),e._time.copy=Date.now()-t;var n=Date.now();p(),e._time.filters=Date.now()-n;var a=Date.now();e.sortOptions.predicate&&!i&&(e.filtered=r("orderBy")(e.filtered,e.sortOptions.predicate,"desc"===e.sortOptions.direction),e.sortCache={data:e.filtered.slice(),predicate:e.sortOptions.predicate,direction:e.sortOptions.direction}),e._time.sort=Date.now()-a,e._time.all=Date.now()-t,e.paginationOptions.totalItems=e.filtered.length}function p(){e.filters.forEach(function(t){var i=t.filterBy,r=t.model,n=t.isInScope?e.$eval(r):e.$parent.$eval(r),o=t.filterType;if(e.customFilters[r])e.filtered=e.customFilters[r](e.filtered,n,i);else if(n&&o){var s=a.getFilterByType(o);s&&(e.filtered=s(e.filtered,n,i))}})}e._gridOptions=e.$eval(i.attr("grid-options")),e._gridActions=e.$eval(i.attr("grid-actions")),e.serverPagination="true"===i.attr("server-pagination"),e.getDataDelay=i.attr("get-delay")||350,e._gridActions||(e.$parent.$eval(i.attr("grid-actions")+"= {}"),e._gridActions=e.$parent.$eval(i.attr("grid-actions"))),e._gridOptions.grid=e,e.filtered=e._gridOptions.data.slice(),e.paginationOptions=e._gridOptions.pagination?angular.copy(e._gridOptions.pagination):{},e.defaultsPaginationOptions={itemsPerPage:e.paginationOptions.itemsPerPage||"10",currentPage:e.paginationOptions.currentPage||1},e.paginationOptions=angular.copy(e.defaultsPaginationOptions),e.sortOptions=e._gridOptions.sort?angular.copy(e._gridOptions.sort):{},e.customFilters=e._gridOptions.customFilters?angular.copy(e._gridOptions.customFilters):{},e.urlSync=e._gridOptions.urlSync,e.$watch("_gridOptions.data",function(i){i&&i.length>-1&&(e.sortCache={},e.filtered=e._gridOptions.data.slice(),e.filters.forEach(function(i){"select"===i.filterType&&(e[i.model+"Options"]=t(e.filtered,i.filterBy))}),e.urlSync?s(n.path()):c())}),e.sort=function(t,i){if(!i){var r=e.sortOptions.predicate===t&&"desc"===e.sortOptions.direction?"asc":"desc";e.sortOptions.direction=r,e.sortOptions.predicate=t}e.paginationOptions.currentPage=1,e.reloadGrid(i)},e.filter=function(){e.paginationOptions.currentPage=1,e.reloadGrid()},e.$on("$locationChangeSuccess",function(){(e.urlSync||e.serverPagination)&&(e.serverPagination&&(clearTimeout(e.getDataTimeout),e.getDataTimeout=setTimeout(l,e.getDataDelay)),e.filtered&&s(n.path()))}),e.reloadGrid=function(t){e.urlSync||e.serverPagination?o(t):c()},e._gridActions.refresh=e.reloadGrid,e._gridActions.filter=e.filter,e._gridActions.sort=e.sort}]).directive("gridItem",["$compile",function(t){return{restrict:"EA",terminal:!0,scope:!1,link:function(e,i,r,n,a){e.serverPagination?i.attr("ng-repeat","item in filtered"):i.attr("ng-repeat","item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage track by $index"),i.removeAttr("grid-item");var o=i[0].outerHTML;i.replaceWith(t(o)(e))}}}]).directive("gridData",["$compile","$animate",function(e){return{restrict:"EA",scope:!0,controller:"gridController",link:function(i,r,n){var a=[],o=r.parent(),s=n.id,l="true"===n.serverPagination;i.serverPagination=l,angular.forEach(angular.element(o[0].querySelectorAll("[sortable]")),function(t){var r=angular.element(t),n=r.attr("sortable");r.attr("ng-class","{'sort-ascent' : sortOptions.predicate ==='"+n+"' && sortOptions.direction === 'asc', 'sort-descent' : sortOptions.predicate === '"+n+"' && sortOptions.direction === 'desc'}"),r.attr("ng-click","sort('"+n+"')"),e(r)(i)}),angular.forEach(document.querySelectorAll("[filter-by]"),function(e){var n=angular.element(e),o=n.attr("filter-by"),l=document.querySelectorAll("[grid-data]")[0],c=l.querySelectorAll('[filter-by="'+o+'"]').length>0,p=n.attr("filter-type")||"",d=n.attr("ng-model"),g=n.attr("disable-url");s&&n.attr("grid-id")&&s!=n.attr("grid-id")||("select"!==p||(i[d+"Options"]=t(i.$eval(r.attr("grid-options")+".data"),o)),!~p.indexOf("date")||n.attr("ng-focus")||n.attr("ng-blur")||(n.attr("ng-focus","filter('{"+d+" : this."+d+"}')"),n.attr("ng-blur","filter('{"+d+" : this."+d+"}')")),d||(d=o,n.attr("ng-model",o),n.attr("ng-change","filter()")),a.push({model:d,isInScope:c,filterBy:o,filterType:p,disableUrl:g}))}),i.filters=a}}}]).factory("filtersFactory",function(){function t(t,e,i){return t.filter(function(t){return!e||!t[i]||t[i]===e})}function e(t,e,i){return t.filter(function(t){return e&&t[i]?~(t[i]+"").toLowerCase().indexOf((e+"").toLowerCase()):!!t[i]})}function i(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return!e||!t[i]||t[i]<=e+86399999})}function r(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return!e||!t[i]||t[i]>=e})}return{getFilterByType:function(n){switch(n){case"select":return t;case"text":return e;case"dateTo":return i;case"dateFrom":return r;default:return null}}}})}(); \ No newline at end of file +!function(){"use strict";function t(t,e){var i=[];return t?(t.forEach(function(t){~i.indexOf(t[e])||i.push(t[e])}),i.map(function(t){return{text:t,value:t}})):void 0}angular.module("dataGrid",[]).filter("startFrom",function(){return function(t,e){return t?(e=+e,t.slice(e)):[]}}).controller("gridController",["$scope","$element","$filter","$location","filtersFactory",function(e,i,r,n,a){function o(){(e.urlSync||e.serverPagination)&&(e.serverPagination&&(clearTimeout(e.getDataTimeout),e.getDataTimeout=setTimeout(l,e.getDataDelay)),e.filtered&&c())}function s(t){var i,r=!1;i="page="+e.paginationOptions.currentPage,e.paginationOptions.itemsPerPage!==e.defaultsPaginationOptions.itemsPerPage&&(i+="&itemsPerPage="+e.paginationOptions.itemsPerPage),e.sortOptions.predicate&&(i+="&sort="+encodeURIComponent(e.sortOptions.predicate+"-"+e.sortOptions.direction)),e.filters.forEach(function(t){var n=t.model,a=t.isInScope?e.$eval(n):e.$parent.$eval(n);if(t.disableUrl)return void(r=!0);if(a){var o;if(a instanceof Date){if(isNaN(a.getTime()))return;o=a.getFullYear()+"-",o+=a.getMonth()<9?"0"+(a.getMonth()+1)+"-":a.getMonth()+1+"-",o+=a.getDate()<10?"0"+a.getDate():a.getDate(),a=o}i+="&"+encodeURIComponent(n)+"="+encodeURIComponent(a)}}),r&&p(),n.search(i),t&&e.$apply()}function c(){var t=n.search(),i={};if(Object.keys(t).forEach(function(e){"page"!==e&&"sort"!==e&&"itemsPerPage"!==e&&(i[e]=t[e])}),e.filters.forEach(function(t){var r=t.model,n=i[r];if(!t.disableUrl){if(~t.filterType.toLowerCase().indexOf("date"))return e.$parent.__evaltmp=n?new Date(n):null,void e.$parent.$eval(r+"=__evaltmp");"select"!==t.filterType||n||(n=""),n&&(t.isInScope?(e.__evaltmp=n,e.$eval(r+"=__evaltmp")):(e.$parent.__evaltmp=n,e.$parent.$eval(r+"=__evaltmp")))}}),e.paginationOptions.itemsPerPage=e.defaultsPaginationOptions.itemsPerPage,e.paginationOptions.currentPage=e.defaultsPaginationOptions.currentPage,t.itemsPerPage&&(e.paginationOptions.itemsPerPage=t.itemsPerPage),t.page&&(!e.serverPagination&&(t.page-1)*e.paginationOptions.itemsPerPage>e.filtered.length?e.paginationOptions.currentPage=1:e.paginationOptions.currentPage=t.page),t.sort){var r=t.sort.split("-");e.sortOptions.predicate=decodeURIComponent(r[0]),e.sortOptions.direction=decodeURIComponent(r[1])}e.serverPagination||p()}function l(){var t="",i=n.search();Object.keys(i).forEach(function(e){t+=e+"="+i[e]+"&"}),t=t.slice(0,-1),!t&&e.sortOptions.predicate?e.sort(e.sortOptions.predicate,!0):e._gridOptions.getData("?"+t,function(t,i){e.filtered=t,e.paginationOptions.totalItems=i})}function p(){var t=Date.now(),i=!1;e._time={},e.sortOptions.predicate&&e.sortCache&&e.sortCache.predicate===e.sortOptions.predicate&&e.sortCache.direction===e.sortOptions.direction?(e.filtered=e.sortCache.data.slice(),i=!0):e.filtered=e._gridOptions.data.slice(),e._time.copy=Date.now()-t;var n=Date.now();d(),e._time.filters=Date.now()-n;var a=Date.now();e.sortOptions.predicate&&!i&&(e.filtered=r("orderBy")(e.filtered,e.sortOptions.predicate,"desc"===e.sortOptions.direction),e.sortCache={data:e.filtered.slice(),predicate:e.sortOptions.predicate,direction:e.sortOptions.direction}),e._time.sort=Date.now()-a,e._time.all=Date.now()-t,e.paginationOptions.totalItems=e.filtered.length}function d(){e.filters.forEach(function(t){var i=t.filterBy,r=t.model,n=t.isInScope?e.$eval(r):e.$parent.$eval(r),o=t.filterType;if(e.customFilters[r])e.filtered=e.customFilters[r](e.filtered,n,i);else if(n&&o){var s=a.getFilterByType(o);s&&(e.filtered=s(e.filtered,n,i))}})}e._gridOptions=e.$eval(i.attr("grid-options")),e._gridActions=e.$eval(i.attr("grid-actions")),e.serverPagination="true"===i.attr("server-pagination"),e.getDataDelay=i.attr("get-delay")||350,e._gridActions||(e.$parent.$eval(i.attr("grid-actions")+"= {}"),e._gridActions=e.$parent.$eval(i.attr("grid-actions"))),e._gridOptions.grid=e,e.filtered=e._gridOptions.data.slice(),e.paginationOptions=e._gridOptions.pagination?angular.copy(e._gridOptions.pagination):{},e.defaultsPaginationOptions={itemsPerPage:e.paginationOptions.itemsPerPage||"10",currentPage:e.paginationOptions.currentPage||1},e.paginationOptions=angular.copy(e.defaultsPaginationOptions),e.sortOptions=e._gridOptions.sort?angular.copy(e._gridOptions.sort):{},e.customFilters=e._gridOptions.customFilters?angular.copy(e._gridOptions.customFilters):{},e.urlSync=e._gridOptions.urlSync,e.$watch("_gridOptions.data",function(i){i&&i.length>-1&&(e.sortCache={},e.filtered=e._gridOptions.data.slice(),e.filters.forEach(function(i){"select"===i.filterType&&(e[i.model+"Options"]=t(e.filtered,i.filterBy))}),e.urlSync?c():p())}),e.sort=function(t,i){if(!i){var r=e.sortOptions.predicate===t&&"desc"===e.sortOptions.direction?"asc":"desc";e.sortOptions.direction=r,e.sortOptions.predicate=t}e.paginationOptions.currentPage=1,e.reloadGrid(i)},e.filter=function(){e.paginationOptions.currentPage=1,e.reloadGrid()},e.$on("$locationChangeSuccess",function(){o()}),e.$on("$stateChangeSuccess",function(t,e){o()}),e.reloadGrid=function(t){e.urlSync||e.serverPagination?s(t):p()},e._gridActions.refresh=e.reloadGrid,e._gridActions.filter=e.filter,e._gridActions.sort=e.sort}]).directive("gridItem",["$compile",function(t){return{restrict:"EA",terminal:!0,scope:!1,link:function(e,i,r,n,a){e.serverPagination?i.attr("ng-repeat","item in filtered"):i.attr("ng-repeat","item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage track by $index"),i.removeAttr("grid-item");var o=i[0].outerHTML;i.replaceWith(t(o)(e))}}}]).directive("gridData",["$compile","$animate",function(e){return{restrict:"EA",scope:!0,controller:"gridController",link:function(i,r,n){var a=[],o=r.parent(),s=n.id,c="true"===n.serverPagination;i.serverPagination=c,angular.forEach(angular.element(o[0].querySelectorAll("[sortable]")),function(t){var r=angular.element(t),n=r.attr("sortable");r.attr("ng-class","{'sort-ascent' : sortOptions.predicate ==='"+n+"' && sortOptions.direction === 'asc', 'sort-descent' : sortOptions.predicate === '"+n+"' && sortOptions.direction === 'desc'}"),r.attr("ng-click","sort('"+n+"')"),e(r)(i)}),angular.forEach(document.querySelectorAll("[filter-by]"),function(e){var n=angular.element(e),o=n.attr("filter-by"),c=document.querySelectorAll("[grid-data]")[0],l=c.querySelectorAll('[filter-by="'+o+'"]').length>0,p=n.attr("filter-type")||"",d=n.attr("ng-model"),g=n.attr("disable-url");s&&n.attr("grid-id")&&s!=n.attr("grid-id")||("select"!==p||(i[d+"Options"]=t(i.$eval(r.attr("grid-options")+".data"),o)),!~p.indexOf("date")||n.attr("ng-focus")||n.attr("ng-blur")||(n.attr("ng-focus","filter('{"+d+" : this."+d+"}')"),n.attr("ng-blur","filter('{"+d+" : this."+d+"}')")),d||(d=o,n.attr("ng-model",o),n.attr("ng-change","filter()")),a.push({model:d,isInScope:l,filterBy:o,filterType:p,disableUrl:g}))}),i.filters=a}}}]).factory("filtersFactory",function(){function t(t,e,i){return t.filter(function(t){return e&&t[i]?t[i]===e:!0})}function e(t,e,i){return t.filter(function(t){return e&&t[i]?~(t[i]+"").toLowerCase().indexOf((e+"").toLowerCase()):!!t[i]})}function i(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]<=e+86399999:!0})}function r(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]>=e:!0})}return{getFilterByType:function(n){switch(n){case"select":return t;case"text":return e;case"dateTo":return i;case"dateFrom":return r;default:return null}}}})}(); \ No newline at end of file diff --git a/src/js/dataGrid.js b/src/js/dataGrid.js index 1bc8aef..1ae356c 100644 --- a/src/js/dataGrid.js +++ b/src/js/dataGrid.js @@ -48,7 +48,7 @@ }); if ($scope.urlSync) { - parseUrl($location.path()); + parseUrl(); } else { applyFilters(); } @@ -71,15 +71,11 @@ }; $scope.$on('$locationChangeSuccess', function () { - if ($scope.urlSync || $scope.serverPagination) { - if ($scope.serverPagination) { - clearTimeout($scope.getDataTimeout); - $scope.getDataTimeout = setTimeout(getData, $scope.getDataDelay); - } - if ($scope.filtered) { - parseUrl($location.path()); - } - } + onChangeStateOrLocation() + }); + + $scope.$on("$stateChangeSuccess", function (event, toState) { + onChangeStateOrLocation() }); $scope.reloadGrid = function (isDefaultSort) { @@ -94,6 +90,18 @@ $scope._gridActions.filter = $scope.filter; $scope._gridActions.sort = $scope.sort; + function onChangeStateOrLocation(){ + if ($scope.urlSync || $scope.serverPagination) { + if ($scope.serverPagination) { + clearTimeout($scope.getDataTimeout); + $scope.getDataTimeout = setTimeout(getData, $scope.getDataDelay); + } + if ($scope.filtered) { + parseUrl(); + } + } + } + function changePath(isDefaultSort) { var path, needApplyFilters = false; @@ -134,27 +142,21 @@ if (needApplyFilters) { applyFilters(); } - $location.path(path); + $location.search(path); if (isDefaultSort) { $scope.$apply(); } } function parseUrl() { - var url = $location.path().slice(1), - params = {}, + var params = $location.search(), customParams = {}; - $scope.params = params; - - url.split('&').forEach(function (urlParam) { - var param = urlParam.split('='); - params[param[0]] = param[1]; - if (param[0] !== 'page' && param[0] !== 'sort' && param[0] !== 'itemsPerPage') { - customParams[decodeURIComponent(param[0])] = decodeURIComponent(param[1]); - } + Object.keys(params).forEach(function(key) { + if (key !== 'page' && key !== 'sort' && key !== 'itemsPerPage') { + customParams[key] = params[key]; } - ); + }); //custom filters $scope.filters.forEach(function (filter) { @@ -216,7 +218,12 @@ } function getData() { - var url = $location.path().slice(1); + var url = ''; + var params = $location.search(); + Object.keys(params).forEach(function(key) { + url += key + '=' + params[key] + '&'; + }); + url = url.slice(0, -1); if (!url && $scope.sortOptions.predicate) { $scope.sort($scope.sortOptions.predicate, true); } else { From 5da6511ecb5431dfd0b08c350383aca5b1ee7c50 Mon Sep 17 00:00:00 2001 From: skozlov Date: Tue, 28 Mar 2017 15:04:13 +0300 Subject: [PATCH 25/53] UI Router - added another state --- demo/bootstrap/js/routerServerPaginationApp.js | 12 ++++++++++++ demo/bootstrap/ui-router.html | 11 ++++++++++- demo/bootstrap/views/anotherView.html | 4 ++++ .../bootstrap/views/router-server-pagination.html | 15 +++++---------- 4 files changed, 31 insertions(+), 11 deletions(-) create mode 100644 demo/bootstrap/views/anotherView.html diff --git a/demo/bootstrap/js/routerServerPaginationApp.js b/demo/bootstrap/js/routerServerPaginationApp.js index e8b28a8..49e7087 100644 --- a/demo/bootstrap/js/routerServerPaginationApp.js +++ b/demo/bootstrap/js/routerServerPaginationApp.js @@ -22,6 +22,11 @@ templateUrl: 'views/router-server-pagination.html', controller: MyAppController }) + .state('anotherView', { + url: '/anotherView', + templateUrl: 'views/anotherView.html', + controller: MyAppController + }) } function MyAppController($scope, myAppFactory, $state) { @@ -34,7 +39,14 @@ direction: 'asc' } }; + $scope.UI = {}; $scope.gridActions = {}; + $scope.goToAnotherState = function() { + $state.go('anotherView'); + }; + $scope.back = function() { + $state.go('orders'); + }; myAppFactory.getStatuses().then(function (resp) { $scope.UI.statusOptions = resp.data; }) diff --git a/demo/bootstrap/ui-router.html b/demo/bootstrap/ui-router.html index 139b239..20b37ed 100644 --- a/demo/bootstrap/ui-router.html +++ b/demo/bootstrap/ui-router.html @@ -36,7 +36,16 @@
    -
    +
    +
    +

    Angular Data Grid - UI Router Server Pagination.

    + UI Router plus all features for server pagination.
    + UI Router can be used in both modes (hash and html5). + Project GitHub +
    +
    +
    +
    diff --git a/demo/bootstrap/views/anotherView.html b/demo/bootstrap/views/anotherView.html new file mode 100644 index 0000000..427c2e4 --- /dev/null +++ b/demo/bootstrap/views/anotherView.html @@ -0,0 +1,4 @@ +

    Another View

    +
    + +
    \ No newline at end of file diff --git a/demo/bootstrap/views/router-server-pagination.html b/demo/bootstrap/views/router-server-pagination.html index d916b5f..1d112af 100644 --- a/demo/bootstrap/views/router-server-pagination.html +++ b/demo/bootstrap/views/router-server-pagination.html @@ -1,12 +1,7 @@
    -
    -

    Angular Data Grid - UI Router Server Pagination.

    - UI Router plus all features for server pagination
    - Features enabled: sorting, filtering (using both in-grid and external controls), pagination and items-per-page functionality. - Angular UI Datepicker used for date controls, although you can use any other framework, plugin or styling. - Project GitHub +
    +
    -
    @@ -117,8 +112,8 @@

    Angular Data Grid - UI Router Server Pagination.

    - - + + - + From 21e04e49794fdc06735fd9a44b35be1d4b3c24f5 Mon Sep 17 00:00:00 2001 From: AlexZ Date: Tue, 28 Mar 2017 15:31:05 +0300 Subject: [PATCH 26/53] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6d10e41..e0416b4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ ##Angular Data Grid + Light, flexible and performant Data Grid for AngularJS apps, with built-in sorting, pagination and filtering options, unified API for client-side and server-side data fetching, seamless synchronization with browser address bar and total freedom in mark-up and styling suitable for your application. Angular 1.3 - 1.6 compliant. From a5eb370d0131ff34995ab201be31224085bf7397 Mon Sep 17 00:00:00 2001 From: AlexZ Date: Tue, 28 Mar 2017 15:31:25 +0300 Subject: [PATCH 27/53] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e0416b4..48ba5dd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -##Angular Data Grid +## Angular Data Grid Light, flexible and performant Data Grid for AngularJS apps, with built-in sorting, pagination and filtering options, unified API for client-side and server-side data fetching, seamless synchronization with browser address bar and total freedom in mark-up and styling suitable for your application. Angular 1.3 - 1.6 compliant. From d6e0508dd54ce84f43c6a6ef7dcbdb81c94a7a4a Mon Sep 17 00:00:00 2001 From: AlexZ Date: Tue, 28 Mar 2017 15:37:16 +0300 Subject: [PATCH 28/53] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 48ba5dd..90c54c6 100644 --- a/README.md +++ b/README.md @@ -239,3 +239,6 @@ Then create in `gridOptions.customFilters` variable named as `ng-model` with fil All filters have optional parameter `disable-url`. If you set it to **true**, URL-synchronization for this filter will be disabled. If you need to use 2 or more grids on page, please add `id` to grids, and then use `grid-id` attribute on filters to specify their corresponding grid. [Example](http://angular-data-grid.github.io/demo/bootstrap/multiple.html) + +### Next / Future + - Port data grid to Angular2? From 3ad18336fe65f0464fd4640156f7ba7515b39dd1 Mon Sep 17 00:00:00 2001 From: Alexander Zhuk Date: Tue, 28 Mar 2017 16:07:41 +0300 Subject: [PATCH 29/53] updating package.json with new version --- package.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 3e5963a..260e070 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "angular-data-grid", - "version": "0.1.0", + "version": "1.0.0", "scripts": { "start": "gulp serve", "prebuild": "npm install" @@ -14,7 +14,7 @@ "gulp-sass": "^2.1.0", "gulp-uglify": "^1.4.2" }, - "description": "Light, flexible and performant Data Grid for AngularJS apps, with built-in sorting, pagination and filtering options, unified API for client-side and server-side data fetching, \r seamless synchronization with browser address bar and total freedom in mark-up and styling suitable for your application. Angular 1.3 - 1.5 compliant.", + "description": "Light, flexible and performant Data Grid for AngularJS apps, with built-in sorting, pagination and filtering options, unified API for client-side and server-side data fetching, \r seamless synchronization with browser address bar and total freedom in mark-up and styling suitable for your application. Angular 1.3 - 1.6 compliant.", "main": "index.html", "devDependencies": {}, "repository": { @@ -23,12 +23,15 @@ }, "keywords": [ "angular data grid", + "angular-data-grid", + "angular grid", + "angular-grid", "data grid", "data grid for angular", "ng-data-grid", "ng-table", "angular table", - "bootstra data grid", + "bootstrap data grid", "material design grid", "data table" ], From 60dda0ebc73ae391a4c43f3b5ef100c08fc24ce1 Mon Sep 17 00:00:00 2001 From: skozlov Date: Tue, 28 Mar 2017 17:04:55 +0300 Subject: [PATCH 30/53] Readme file was updated (urlSync) --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 90c54c6..55011cd 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Demo Angular UI Router: http://angular-data-grid.github.io/demo/bootstrap/ui-rou ### Features - Does not have any hard-coded template so you can choose any mark-up you need, from basic `
    Order #Date PlacedOrder # Date Placed TotalTotal
    ` layout to any `
    ` structure. - Easily switch between the most popular Bootstrap and Google Material theming, or apply your own CSS theme just by changing several CSS classes. - - Built-in sync with browser address bar (URL), so you can copy-n-paste sorting/filtering/pagination results URL and open it in other browser / send to anyone - even if pagination / filtering are done on a client-side. + - Built-in sync with browser address bar (URL), so you can copy-n-paste sorting/filtering/pagination results URL and open it in other browser / send to anyone - even if pagination / filtering are done on a client-side. [See details](#url-synchronization) - Support of [Angular UI Router](https://github.com/angular-ui/ui-router) navigation. - Unlike most part of other Angular DataGrids, we intentionally use non-isolated scope of the directive to maximize flexibility, so it can be easily synchronized with any data changes inside your controller. NOTE! With great power comes great responsibility, so use non-isolated API wisely. @@ -235,9 +235,12 @@ Then create in `gridOptions.customFilters` variable named as `ng-model` with fil ``` -### Others -All filters have optional parameter `disable-url`. If you set it to **true**, URL-synchronization for this filter will be disabled. +### Url Synchronization +You can disable/enable URL-synchronization for whole grid. Just set `gridOptions.urlSync` to **false**/**true** +All filters have optional parameter `disable-url`. If you set it to **true**, URL-synchronization for this filter will be disabled. + +### Others If you need to use 2 or more grids on page, please add `id` to grids, and then use `grid-id` attribute on filters to specify their corresponding grid. [Example](http://angular-data-grid.github.io/demo/bootstrap/multiple.html) ### Next / Future From 16f87e1acd126a526ccd635afb401548436d1e87 Mon Sep 17 00:00:00 2001 From: AlexZ Date: Tue, 28 Mar 2017 17:26:53 +0300 Subject: [PATCH 31/53] Update README.md --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 55011cd..e10d9c3 100644 --- a/README.md +++ b/README.md @@ -235,13 +235,16 @@ Then create in `gridOptions.customFilters` variable named as `ng-model` with fil ``` -### Url Synchronization -You can disable/enable URL-synchronization for whole grid. Just set `gridOptions.urlSync` to **false**/**true** -All filters have optional parameter `disable-url`. If you set it to **true**, URL-synchronization for this filter will be disabled. +### URL Synchronization +You can disable/enable URL synchronization for the whole grid or on a level of particular filter. +Global parameter `gridOptions.urlSync` (boolean) works for the whole grid. -### Others +Each filter has optional parameter `disable-url` (boolean). If you set it to **true**, URL-synchronization for this particular filter will be disabled. + + +### Multiple grids on page If you need to use 2 or more grids on page, please add `id` to grids, and then use `grid-id` attribute on filters to specify their corresponding grid. [Example](http://angular-data-grid.github.io/demo/bootstrap/multiple.html) ### Next / Future - - Port data grid to Angular2? + - Port to Angular2? From c39897d759abf3437b8b676d1e56236628884310 Mon Sep 17 00:00:00 2001 From: AlexZ Date: Tue, 28 Mar 2017 17:28:23 +0300 Subject: [PATCH 32/53] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e10d9c3..094fab6 100644 --- a/README.md +++ b/README.md @@ -240,7 +240,7 @@ You can disable/enable URL synchronization for the whole grid or on a level of p Global parameter `gridOptions.urlSync` (boolean) works for the whole grid. -Each filter has optional parameter `disable-url` (boolean). If you set it to **true**, URL-synchronization for this particular filter will be disabled. +Each filter has optional parameter `disable-url` (boolean, default is 'false'). If you set it to **true**, URL-synchronization for this particular filter will be disabled. ### Multiple grids on page From 219d41d792e16def3a6fdda3d64491ddc88f31e2 Mon Sep 17 00:00:00 2001 From: AlexZ Date: Tue, 28 Mar 2017 17:28:45 +0300 Subject: [PATCH 33/53] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 094fab6..a453e66 100644 --- a/README.md +++ b/README.md @@ -238,7 +238,7 @@ Then create in `gridOptions.customFilters` variable named as `ng-model` with fil ### URL Synchronization You can disable/enable URL synchronization for the whole grid or on a level of particular filter. -Global parameter `gridOptions.urlSync` (boolean) works for the whole grid. +Global parameter `gridOptions.urlSync` (boolean, default is 'false') works for the whole grid. Each filter has optional parameter `disable-url` (boolean, default is 'false'). If you set it to **true**, URL-synchronization for this particular filter will be disabled. From 1842d577b3d94b888498a1e6fdd54a4a723bd962 Mon Sep 17 00:00:00 2001 From: AndreyChayko Date: Mon, 10 Apr 2017 12:33:25 +0300 Subject: [PATCH 34/53] Support fixed header columns (#33) * Fix Issue #29: Added initial structure * Fix #29: Added samples for bootstrap and material-design themes. Added dataGridUtils module and fixed-header directive * Fix #29: Code refactoring * Fix Issue #29: Modifications to css for fixed-header * Fix Issue #29: Removed unused code * Fix Issue #29: Changed file structure * Fix Issue #29: Added documentation for fixed header to bootstrap sample * Fix Issue #29: Added documentation to material sample * Fix Issue #29: Fixed description of the issue with md-content * Fix Issue #29: Applied changes to documentation. --- demo/fixed-header/angular-md-grid.html | 270 +++++++++++++++ demo/fixed-header/bootstrap-grid.html | 307 ++++++++++++++++++ .../css/fixed-header.bootstrap.css | 16 + .../css/fixed-header.material.css | 8 + demo/fixed-header/js/bootstrap/demoApp.js | 24 ++ .../js/material-design/demoApp.js | 23 ++ .../scss/fixed-header.bootstrap.scss | 25 ++ .../scss/fixed-header.material.scss | 14 + dist/css/fixedHeader/fixed-header.css | 10 + dist/dataGrid.js | 3 +- dist/dataGrid.min.js | 2 +- dist/dataGridUtils.js | 89 +++++ dist/dataGridUtils.min.js | 1 + dist/loading-bar.min.js | 2 +- dist/pagination.min.js | 2 +- gulpfile.js | 20 +- src/js/dataGrid.js | 3 +- src/js/directives/dataGridUtils.js | 4 + .../directives/fixedHeader/fixed-header.scss | 15 + src/js/directives/fixedHeader/fixedHeader.js | 85 +++++ 20 files changed, 917 insertions(+), 6 deletions(-) create mode 100644 demo/fixed-header/angular-md-grid.html create mode 100644 demo/fixed-header/bootstrap-grid.html create mode 100644 demo/fixed-header/css/fixed-header.bootstrap.css create mode 100644 demo/fixed-header/css/fixed-header.material.css create mode 100644 demo/fixed-header/js/bootstrap/demoApp.js create mode 100644 demo/fixed-header/js/material-design/demoApp.js create mode 100644 demo/fixed-header/scss/fixed-header.bootstrap.scss create mode 100644 demo/fixed-header/scss/fixed-header.material.scss create mode 100644 dist/css/fixedHeader/fixed-header.css create mode 100644 dist/dataGridUtils.js create mode 100644 dist/dataGridUtils.min.js create mode 100644 src/js/directives/dataGridUtils.js create mode 100644 src/js/directives/fixedHeader/fixed-header.scss create mode 100644 src/js/directives/fixedHeader/fixedHeader.js diff --git a/demo/fixed-header/angular-md-grid.html b/demo/fixed-header/angular-md-grid.html new file mode 100644 index 0000000..134befc --- /dev/null +++ b/demo/fixed-header/angular-md-grid.html @@ -0,0 +1,270 @@ + + + + + Angular Data Grid - Material Design + + + + + + + + + +
    + +
    + Angular Data Grid — Material Design + + + + + Change theme + arrow_drop_down + + + + + Bootstrap Design + + + Material Design + + + +
    +
    + +
    +
    +

    Angular Data Grid sample using Material Design styling

    + +

    Features enabled: sorting, filtering, sync with browser URLs, pagination and item-per-page functionality. + Out-of-box Angular Material layout and + input controls used, + along with Material Design Light default CSS for + grid styling. + Project GitHub

    + +
    +

    How To Freeze Table Header

    +

    Using HTML Layout

    +
    +

    The first option is to split table header and table body in two tables. + One way to do this is to follow the next steps:

    +
      +
    • Use the next styles (with any fixed height) applied to table body container to make it scrollable:
      + .div-table-body { height: 600px; overflow-x: auto; overflow-y: scroll; }
      +
    • +
    • Make sure that th elements have the same padding as td elements have.
    • +
    • Use padding-right with the value of scroll bar width to make an offset for the table contains header.
    • +
    • Use width attribute for columns to sync widths.
    • +
    +

    Code Sample: +

    +<table>
    +    <thead>
    +        ...
    +    </thead>
    +</table>
    +<table>
    +    <tbody class="div-table-body">
    +        ...
    +    </tbody>
    +</table>
    +        
    +

    +
    +

    Using Stand-alone Directive

    +
    +

    Another option is to use the directive fixed-header that can be injected to the Data Grid like a separate module dataGridUtils.

    +

    To make it work it is needed to perform next steps:

    +
      +
    • Include script to your application:
      + <script src="bower_components/angular-data-grid/dist/dataGridUtils.min.js"></script> +
    • +
    • Include css stylesheets to your application:
      + <link rel="stylesheet" href="bower_components/angular-data-grid/css/fixedHeader/fixed-header.css"> +
    • +
    • Inject dataGridUtils dependency in your module:
      + angular.module('myApp', ['dataGrid', ‘dataGridUtils.fixedHeader’]) +
    • +
    • Apply the directive fixed-header to the grid table:
      + <table class="table" fixed-header> +
    • +
    +

    The directive uses z-index: 99 if your page uses the same value or higher please make appropriate changes to fixed-header.scss file.

    +

    The directive also has additional attribute offset-from-element. + It is needed if you already have some other elements with fixed position above the table. + In this case you need to pass a class or id of the very last element (if there are several) to this attribute + to make the directive take + into consideration that header needs to be fixed with offset from above elements.

    +

    Example:
    + <table class="table" fixed-header offset-from-element + =”.the-class-on-above-fixed-element”>
    + or
    + <table class="table" fixed-header offset-from-element + =”=”#the-id-on-above-fixed-element”> +

    +
    +

    The directive subscribes on scroll event, but the event is not fired when directive is used inside <md-content>, so to make it work please use the directive outside the <md-content> container. + For more information about this problem please review this issue. +

    +
    +
    +
    +
    +
    +
    + + + +
    +
    + +
    +
    + +
    +
    + Clear Dates + +
    +
    +
    +
    +
    + {{filtered.length}} items total +
    +
    +
    + + + + 10 + 25 + 50 + 75 + + +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + +
    + Order # + + + All Statuses + + {{option.text}} + + + + Date Placed + + Total +
    + +
    +
    +
    + + + + 10 + 25 + 50 + 75 + + +
    +
    +
    + CodePen +
    +

    See the Pen eJWWpM by AngularDataGrid (@AngularDataGrid) on CodePen. +

    + +
    +
    +
    +
    + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/fixed-header/bootstrap-grid.html b/demo/fixed-header/bootstrap-grid.html new file mode 100644 index 0000000..bf2d003 --- /dev/null +++ b/demo/fixed-header/bootstrap-grid.html @@ -0,0 +1,307 @@ + + + + + Angular Data Grid - Bootstrap Design + + + + + + + + + +
    +
    +

    Angular Data Grid sample using out-of-box Bootstrap styling

    + Features enabled: sorting, filtering (using both in-grid and external controls), sync with browser URLs, pagination and items-per-page functionality. + Angular UI Datepicker used for date controls, although you can use any other framework, plugin or styling. + Project GitHub +
    +
    +

    How To Freeze Table Header

    +

    Using HTML Layout

    +
    +

    The first option is to split table header and table body in two tables. + One way to do this is to follow the next steps:

    +
      +
    • Use the next styles (with any fixed height) applied to table body container to make it scrollable:
      + .div-table-body { height: 600px; overflow-x: auto; overflow-y: scroll; } +
    • +
    • Make sure that th elements have the same padding as td elements have.
    • +
    • Use padding-right with the value of scroll bar width to make an offset for the table contains header.
    • +
    • Use width attribute for columns to sync widths.
    • +
    +

    Code Sample: +

    +<table>
    +    <thead>
    +        ...
    +    </thead>
    +</table>
    +<table>
    +    <tbody class="div-table-body">
    +        ...
    +    </tbody>
    +</table>
    +        
    +

    +
    +

    Using Stand-alone Directive

    +
    +

    Another option is to use the directive fixed-header that can be injected to the Data Grid like a separate module dataGridUtils.

    +

    To make it work it is needed to perform next steps:

    +
      +
    • Include script to your application:
      + <script src="bower_components/angular-data-grid/dist/dataGridUtils.min.js"></script> +
    • +
    • Include css stylesheets to your application:
      + <link rel="stylesheet" href="bower_components/angular-data-grid/css/fixedHeader/fixed-header.css"> +
    • +
    • Inject dataGridUtils dependency in your module:
      + angular.module('myApp', ['dataGrid', ‘dataGridUtils.fixedHeader’]) +
    • +
    • Apply the directive fixed-header to the grid table:
      + <table class="table" fixed-header> +
    • +
    +

    The directive uses z-index: 99 if your page uses the same value or higher please make appropriate changes to fixed-header.scss file.

    +

    The directive also has additional attribute offset-from-element. + It is needed if you already have some other elements with fixed position above the table. + In this case you need to pass a class or id of the very last element (if there are several) to this attribute + to make the directive take + into consideration that header needs to be fixed with offset from above elements.

    +

    Example:
    + <table class="table" fixed-header offset-from-element + =”.the-class-on-above-fixed-element”>
    + or
    + <table class="table" fixed-header offset-from-element + =”=”#the-id-on-above-fixed-element”> +

    +
    +
    +

    Additional Demos

    + +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    + + + + +
    +
    +
    +
    +
    + + +
    + + + + +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    + {{filtered.length}} items total +
    +
    +
    +
    + +
    +
    + + +
    +
    +
    +
    + + + + + + + + + + + + + + + + + +
    + Order # + + Date Placed + + + + Total +
    +
    +
    + +
    +
    + + +
    +
    +
    +
    +
    +
    +
    + +
    +

    See the Pen xZddZm by AngularDataGrid (@AngularDataGrid) on CodePen.

    + +
    +
    +
    +
    + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/fixed-header/css/fixed-header.bootstrap.css b/demo/fixed-header/css/fixed-header.bootstrap.css new file mode 100644 index 0000000..421dc34 --- /dev/null +++ b/demo/fixed-header/css/fixed-header.bootstrap.css @@ -0,0 +1,16 @@ +.fixed-header { + border: none; } + .fixed-header tr { + background-color: #fff; } + +.tbody-offset:before { + color: white; + height: 60px; } + +.fixed-nav { + position: fixed; + width: 100%; + z-index: 5; } + +.padding-top-50 { + padding-top: 50px; } diff --git a/demo/fixed-header/css/fixed-header.material.css b/demo/fixed-header/css/fixed-header.material.css new file mode 100644 index 0000000..d1ce846 --- /dev/null +++ b/demo/fixed-header/css/fixed-header.material.css @@ -0,0 +1,8 @@ +.fixed-header { + border: 1px solid rgba(0, 0, 0, 0.12); } + .fixed-header tr { + background-color: #fff; } + +.tbody-offset:before { + color: white; + height: 60px; } diff --git a/demo/fixed-header/js/bootstrap/demoApp.js b/demo/fixed-header/js/bootstrap/demoApp.js new file mode 100644 index 0000000..042d439 --- /dev/null +++ b/demo/fixed-header/js/bootstrap/demoApp.js @@ -0,0 +1,24 @@ +angular.module('myApp', ['ui.bootstrap', 'dataGrid', 'pagination', 'dataGridUtils.fixedHeader']) + .controller('myAppController', ['$scope', 'myAppFactory', function ($scope, myAppFactory) { + + $scope.gridOptions = { + data: [], + urlSync: true + }; + + myAppFactory.getData().then(function (responseData) { + $scope.gridOptions.data = responseData.data; + }); + + }]) + .factory('myAppFactory', function ($http) { + return { + getData: function () { + return $http({ + method: 'GET', + url: 'https://angular-data-grid.github.io/demo/data.json' + }); + } + } + }); + diff --git a/demo/fixed-header/js/material-design/demoApp.js b/demo/fixed-header/js/material-design/demoApp.js new file mode 100644 index 0000000..2f108af --- /dev/null +++ b/demo/fixed-header/js/material-design/demoApp.js @@ -0,0 +1,23 @@ +angular.module('myApp', ['dataGrid', 'pagination', 'ngMaterial', 'dataGridUtils.fixedHeader']) + .controller('myAppController', ['$scope', 'myAppFactory', function ($scope, myAppFactory) { + + $scope.gridOptions = { + data: [], + urlSync: true + }; + myAppFactory.getData().then(function (responseData) { + $scope.gridOptions.data = responseData.data; + }); + + }]) + .factory('myAppFactory', function ($http) { + return { + getData: function () { + return $http({ + method: 'GET', + url: 'https://angular-data-grid.github.io/demo/data.json' + }); + } + } + }); + diff --git a/demo/fixed-header/scss/fixed-header.bootstrap.scss b/demo/fixed-header/scss/fixed-header.bootstrap.scss new file mode 100644 index 0000000..8c6ff62 --- /dev/null +++ b/demo/fixed-header/scss/fixed-header.bootstrap.scss @@ -0,0 +1,25 @@ +//styles specific to bootstrap sample (not required) +.fixed-header { + border: none; + tr { + background-color: #fff; + } +} + +.tbody-offset { + &:before { + color: white; + height: 60px; + } +} + +.fixed-nav { + position: fixed; + width: 100%; + z-index: 5; +} + +.padding-top-50 { + padding-top: 50px; +} + diff --git a/demo/fixed-header/scss/fixed-header.material.scss b/demo/fixed-header/scss/fixed-header.material.scss new file mode 100644 index 0000000..b1dfee6 --- /dev/null +++ b/demo/fixed-header/scss/fixed-header.material.scss @@ -0,0 +1,14 @@ +//styles specific to material design sample (not required) +.fixed-header { + border: 1px solid rgba(0,0,0,.12); + tr { + background-color: #fff; + } +} + +.tbody-offset { + &:before { + color: white; + height: 60px; + } +} \ No newline at end of file diff --git a/dist/css/fixedHeader/fixed-header.css b/dist/css/fixedHeader/fixed-header.css new file mode 100644 index 0000000..29c52fc --- /dev/null +++ b/dist/css/fixedHeader/fixed-header.css @@ -0,0 +1,10 @@ +.fixed-header { + top: 0; + position: fixed; + width: auto; + display: table; + z-index: 99; } + +.tbody-offset:before { + content: " "; + display: block; } diff --git a/dist/dataGrid.js b/dist/dataGrid.js index 1ae356c..7ed9847 100644 --- a/dist/dataGrid.js +++ b/dist/dataGrid.js @@ -12,7 +12,7 @@ return []; } }) - .controller('gridController', ['$scope', '$element', '$filter', '$location', 'filtersFactory', function ($scope, $element, $filter, $location, filtersFactory) { + .controller('gridController', ['$scope', '$rootScope', '$element', '$filter', '$location', 'filtersFactory', function ($scope, $rootScope, $element, $filter, $location, filtersFactory) { // values by default $scope._gridOptions = $scope.$eval($element.attr('grid-options')); $scope._gridActions = $scope.$eval($element.attr('grid-actions')); @@ -84,6 +84,7 @@ } else { applyFilters(); } + $rootScope.$broadcast('gridReloaded'); }; $scope._gridActions.refresh = $scope.reloadGrid; diff --git a/dist/dataGrid.min.js b/dist/dataGrid.min.js index c0ba104..2789310 100644 --- a/dist/dataGrid.min.js +++ b/dist/dataGrid.min.js @@ -1 +1 @@ -!function(){"use strict";function t(t,e){var i=[];return t?(t.forEach(function(t){~i.indexOf(t[e])||i.push(t[e])}),i.map(function(t){return{text:t,value:t}})):void 0}angular.module("dataGrid",[]).filter("startFrom",function(){return function(t,e){return t?(e=+e,t.slice(e)):[]}}).controller("gridController",["$scope","$element","$filter","$location","filtersFactory",function(e,i,r,n,a){function o(){(e.urlSync||e.serverPagination)&&(e.serverPagination&&(clearTimeout(e.getDataTimeout),e.getDataTimeout=setTimeout(l,e.getDataDelay)),e.filtered&&c())}function s(t){var i,r=!1;i="page="+e.paginationOptions.currentPage,e.paginationOptions.itemsPerPage!==e.defaultsPaginationOptions.itemsPerPage&&(i+="&itemsPerPage="+e.paginationOptions.itemsPerPage),e.sortOptions.predicate&&(i+="&sort="+encodeURIComponent(e.sortOptions.predicate+"-"+e.sortOptions.direction)),e.filters.forEach(function(t){var n=t.model,a=t.isInScope?e.$eval(n):e.$parent.$eval(n);if(t.disableUrl)return void(r=!0);if(a){var o;if(a instanceof Date){if(isNaN(a.getTime()))return;o=a.getFullYear()+"-",o+=a.getMonth()<9?"0"+(a.getMonth()+1)+"-":a.getMonth()+1+"-",o+=a.getDate()<10?"0"+a.getDate():a.getDate(),a=o}i+="&"+encodeURIComponent(n)+"="+encodeURIComponent(a)}}),r&&p(),n.search(i),t&&e.$apply()}function c(){var t=n.search(),i={};if(Object.keys(t).forEach(function(e){"page"!==e&&"sort"!==e&&"itemsPerPage"!==e&&(i[e]=t[e])}),e.filters.forEach(function(t){var r=t.model,n=i[r];if(!t.disableUrl){if(~t.filterType.toLowerCase().indexOf("date"))return e.$parent.__evaltmp=n?new Date(n):null,void e.$parent.$eval(r+"=__evaltmp");"select"!==t.filterType||n||(n=""),n&&(t.isInScope?(e.__evaltmp=n,e.$eval(r+"=__evaltmp")):(e.$parent.__evaltmp=n,e.$parent.$eval(r+"=__evaltmp")))}}),e.paginationOptions.itemsPerPage=e.defaultsPaginationOptions.itemsPerPage,e.paginationOptions.currentPage=e.defaultsPaginationOptions.currentPage,t.itemsPerPage&&(e.paginationOptions.itemsPerPage=t.itemsPerPage),t.page&&(!e.serverPagination&&(t.page-1)*e.paginationOptions.itemsPerPage>e.filtered.length?e.paginationOptions.currentPage=1:e.paginationOptions.currentPage=t.page),t.sort){var r=t.sort.split("-");e.sortOptions.predicate=decodeURIComponent(r[0]),e.sortOptions.direction=decodeURIComponent(r[1])}e.serverPagination||p()}function l(){var t="",i=n.search();Object.keys(i).forEach(function(e){t+=e+"="+i[e]+"&"}),t=t.slice(0,-1),!t&&e.sortOptions.predicate?e.sort(e.sortOptions.predicate,!0):e._gridOptions.getData("?"+t,function(t,i){e.filtered=t,e.paginationOptions.totalItems=i})}function p(){var t=Date.now(),i=!1;e._time={},e.sortOptions.predicate&&e.sortCache&&e.sortCache.predicate===e.sortOptions.predicate&&e.sortCache.direction===e.sortOptions.direction?(e.filtered=e.sortCache.data.slice(),i=!0):e.filtered=e._gridOptions.data.slice(),e._time.copy=Date.now()-t;var n=Date.now();d(),e._time.filters=Date.now()-n;var a=Date.now();e.sortOptions.predicate&&!i&&(e.filtered=r("orderBy")(e.filtered,e.sortOptions.predicate,"desc"===e.sortOptions.direction),e.sortCache={data:e.filtered.slice(),predicate:e.sortOptions.predicate,direction:e.sortOptions.direction}),e._time.sort=Date.now()-a,e._time.all=Date.now()-t,e.paginationOptions.totalItems=e.filtered.length}function d(){e.filters.forEach(function(t){var i=t.filterBy,r=t.model,n=t.isInScope?e.$eval(r):e.$parent.$eval(r),o=t.filterType;if(e.customFilters[r])e.filtered=e.customFilters[r](e.filtered,n,i);else if(n&&o){var s=a.getFilterByType(o);s&&(e.filtered=s(e.filtered,n,i))}})}e._gridOptions=e.$eval(i.attr("grid-options")),e._gridActions=e.$eval(i.attr("grid-actions")),e.serverPagination="true"===i.attr("server-pagination"),e.getDataDelay=i.attr("get-delay")||350,e._gridActions||(e.$parent.$eval(i.attr("grid-actions")+"= {}"),e._gridActions=e.$parent.$eval(i.attr("grid-actions"))),e._gridOptions.grid=e,e.filtered=e._gridOptions.data.slice(),e.paginationOptions=e._gridOptions.pagination?angular.copy(e._gridOptions.pagination):{},e.defaultsPaginationOptions={itemsPerPage:e.paginationOptions.itemsPerPage||"10",currentPage:e.paginationOptions.currentPage||1},e.paginationOptions=angular.copy(e.defaultsPaginationOptions),e.sortOptions=e._gridOptions.sort?angular.copy(e._gridOptions.sort):{},e.customFilters=e._gridOptions.customFilters?angular.copy(e._gridOptions.customFilters):{},e.urlSync=e._gridOptions.urlSync,e.$watch("_gridOptions.data",function(i){i&&i.length>-1&&(e.sortCache={},e.filtered=e._gridOptions.data.slice(),e.filters.forEach(function(i){"select"===i.filterType&&(e[i.model+"Options"]=t(e.filtered,i.filterBy))}),e.urlSync?c():p())}),e.sort=function(t,i){if(!i){var r=e.sortOptions.predicate===t&&"desc"===e.sortOptions.direction?"asc":"desc";e.sortOptions.direction=r,e.sortOptions.predicate=t}e.paginationOptions.currentPage=1,e.reloadGrid(i)},e.filter=function(){e.paginationOptions.currentPage=1,e.reloadGrid()},e.$on("$locationChangeSuccess",function(){o()}),e.$on("$stateChangeSuccess",function(t,e){o()}),e.reloadGrid=function(t){e.urlSync||e.serverPagination?s(t):p()},e._gridActions.refresh=e.reloadGrid,e._gridActions.filter=e.filter,e._gridActions.sort=e.sort}]).directive("gridItem",["$compile",function(t){return{restrict:"EA",terminal:!0,scope:!1,link:function(e,i,r,n,a){e.serverPagination?i.attr("ng-repeat","item in filtered"):i.attr("ng-repeat","item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage track by $index"),i.removeAttr("grid-item");var o=i[0].outerHTML;i.replaceWith(t(o)(e))}}}]).directive("gridData",["$compile","$animate",function(e){return{restrict:"EA",scope:!0,controller:"gridController",link:function(i,r,n){var a=[],o=r.parent(),s=n.id,c="true"===n.serverPagination;i.serverPagination=c,angular.forEach(angular.element(o[0].querySelectorAll("[sortable]")),function(t){var r=angular.element(t),n=r.attr("sortable");r.attr("ng-class","{'sort-ascent' : sortOptions.predicate ==='"+n+"' && sortOptions.direction === 'asc', 'sort-descent' : sortOptions.predicate === '"+n+"' && sortOptions.direction === 'desc'}"),r.attr("ng-click","sort('"+n+"')"),e(r)(i)}),angular.forEach(document.querySelectorAll("[filter-by]"),function(e){var n=angular.element(e),o=n.attr("filter-by"),c=document.querySelectorAll("[grid-data]")[0],l=c.querySelectorAll('[filter-by="'+o+'"]').length>0,p=n.attr("filter-type")||"",d=n.attr("ng-model"),g=n.attr("disable-url");s&&n.attr("grid-id")&&s!=n.attr("grid-id")||("select"!==p||(i[d+"Options"]=t(i.$eval(r.attr("grid-options")+".data"),o)),!~p.indexOf("date")||n.attr("ng-focus")||n.attr("ng-blur")||(n.attr("ng-focus","filter('{"+d+" : this."+d+"}')"),n.attr("ng-blur","filter('{"+d+" : this."+d+"}')")),d||(d=o,n.attr("ng-model",o),n.attr("ng-change","filter()")),a.push({model:d,isInScope:l,filterBy:o,filterType:p,disableUrl:g}))}),i.filters=a}}}]).factory("filtersFactory",function(){function t(t,e,i){return t.filter(function(t){return e&&t[i]?t[i]===e:!0})}function e(t,e,i){return t.filter(function(t){return e&&t[i]?~(t[i]+"").toLowerCase().indexOf((e+"").toLowerCase()):!!t[i]})}function i(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]<=e+86399999:!0})}function r(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return e&&t[i]?t[i]>=e:!0})}return{getFilterByType:function(n){switch(n){case"select":return t;case"text":return e;case"dateTo":return i;case"dateFrom":return r;default:return null}}}})}(); \ No newline at end of file +!function(){"use strict";function t(t,e){var i=[];if(t)return t.forEach(function(t){~i.indexOf(t[e])||i.push(t[e])}),i.map(function(t){return{text:t,value:t}})}angular.module("dataGrid",[]).filter("startFrom",function(){return function(t,e){return t?(e=+e,t.slice(e)):[]}}).controller("gridController",["$scope","$rootScope","$element","$filter","$location","filtersFactory",function(e,i,r,n,a,o){function s(){(e.urlSync||e.serverPagination)&&(e.serverPagination&&(clearTimeout(e.getDataTimeout),e.getDataTimeout=setTimeout(p,e.getDataDelay)),e.filtered&&l())}function c(t){var i,r=!1;i="page="+e.paginationOptions.currentPage,e.paginationOptions.itemsPerPage!==e.defaultsPaginationOptions.itemsPerPage&&(i+="&itemsPerPage="+e.paginationOptions.itemsPerPage),e.sortOptions.predicate&&(i+="&sort="+encodeURIComponent(e.sortOptions.predicate+"-"+e.sortOptions.direction)),e.filters.forEach(function(t){var n=t.model,a=t.isInScope?e.$eval(n):e.$parent.$eval(n);if(t.disableUrl)return void(r=!0);if(a){var o;if(a instanceof Date){if(isNaN(a.getTime()))return;o=a.getFullYear()+"-",o+=a.getMonth()<9?"0"+(a.getMonth()+1)+"-":a.getMonth()+1+"-",o+=a.getDate()<10?"0"+a.getDate():a.getDate(),a=o}i+="&"+encodeURIComponent(n)+"="+encodeURIComponent(a)}}),r&&d(),a.search(i),t&&e.$apply()}function l(){var t=a.search(),i={};if(Object.keys(t).forEach(function(e){"page"!==e&&"sort"!==e&&"itemsPerPage"!==e&&(i[e]=t[e])}),e.filters.forEach(function(t){var r=t.model,n=i[r];if(!t.disableUrl){if(~t.filterType.toLowerCase().indexOf("date"))return e.$parent.__evaltmp=n?new Date(n):null,void e.$parent.$eval(r+"=__evaltmp");"select"!==t.filterType||n||(n=""),n&&(t.isInScope?(e.__evaltmp=n,e.$eval(r+"=__evaltmp")):(e.$parent.__evaltmp=n,e.$parent.$eval(r+"=__evaltmp")))}}),e.paginationOptions.itemsPerPage=e.defaultsPaginationOptions.itemsPerPage,e.paginationOptions.currentPage=e.defaultsPaginationOptions.currentPage,t.itemsPerPage&&(e.paginationOptions.itemsPerPage=t.itemsPerPage),t.page&&(!e.serverPagination&&(t.page-1)*e.paginationOptions.itemsPerPage>e.filtered.length?e.paginationOptions.currentPage=1:e.paginationOptions.currentPage=t.page),t.sort){var r=t.sort.split("-");e.sortOptions.predicate=decodeURIComponent(r[0]),e.sortOptions.direction=decodeURIComponent(r[1])}e.serverPagination||d()}function p(){var t="",i=a.search();Object.keys(i).forEach(function(e){t+=e+"="+i[e]+"&"}),t=t.slice(0,-1),!t&&e.sortOptions.predicate?e.sort(e.sortOptions.predicate,!0):e._gridOptions.getData("?"+t,function(t,i){e.filtered=t,e.paginationOptions.totalItems=i})}function d(){var t=Date.now(),i=!1;e._time={},e.sortOptions.predicate&&e.sortCache&&e.sortCache.predicate===e.sortOptions.predicate&&e.sortCache.direction===e.sortOptions.direction?(e.filtered=e.sortCache.data.slice(),i=!0):e.filtered=e._gridOptions.data.slice(),e._time.copy=Date.now()-t;var r=Date.now();g(),e._time.filters=Date.now()-r;var a=Date.now();e.sortOptions.predicate&&!i&&(e.filtered=n("orderBy")(e.filtered,e.sortOptions.predicate,"desc"===e.sortOptions.direction),e.sortCache={data:e.filtered.slice(),predicate:e.sortOptions.predicate,direction:e.sortOptions.direction}),e._time.sort=Date.now()-a,e._time.all=Date.now()-t,e.paginationOptions.totalItems=e.filtered.length}function g(){e.filters.forEach(function(t){var i=t.filterBy,r=t.model,n=t.isInScope?e.$eval(r):e.$parent.$eval(r),a=t.filterType;if(e.customFilters[r])e.filtered=e.customFilters[r](e.filtered,n,i);else if(n&&a){var s=o.getFilterByType(a);s&&(e.filtered=s(e.filtered,n,i))}})}e._gridOptions=e.$eval(r.attr("grid-options")),e._gridActions=e.$eval(r.attr("grid-actions")),e.serverPagination="true"===r.attr("server-pagination"),e.getDataDelay=r.attr("get-delay")||350,e._gridActions||(e.$parent.$eval(r.attr("grid-actions")+"= {}"),e._gridActions=e.$parent.$eval(r.attr("grid-actions"))),e._gridOptions.grid=e,e.filtered=e._gridOptions.data.slice(),e.paginationOptions=e._gridOptions.pagination?angular.copy(e._gridOptions.pagination):{},e.defaultsPaginationOptions={itemsPerPage:e.paginationOptions.itemsPerPage||"10",currentPage:e.paginationOptions.currentPage||1},e.paginationOptions=angular.copy(e.defaultsPaginationOptions),e.sortOptions=e._gridOptions.sort?angular.copy(e._gridOptions.sort):{},e.customFilters=e._gridOptions.customFilters?angular.copy(e._gridOptions.customFilters):{},e.urlSync=e._gridOptions.urlSync,e.$watch("_gridOptions.data",function(i){i&&i.length>-1&&(e.sortCache={},e.filtered=e._gridOptions.data.slice(),e.filters.forEach(function(i){"select"===i.filterType&&(e[i.model+"Options"]=t(e.filtered,i.filterBy))}),e.urlSync?l():d())}),e.sort=function(t,i){if(!i){var r=e.sortOptions.predicate===t&&"desc"===e.sortOptions.direction?"asc":"desc";e.sortOptions.direction=r,e.sortOptions.predicate=t}e.paginationOptions.currentPage=1,e.reloadGrid(i)},e.filter=function(){e.paginationOptions.currentPage=1,e.reloadGrid()},e.$on("$locationChangeSuccess",function(){s()}),e.$on("$stateChangeSuccess",function(t,e){s()}),e.reloadGrid=function(t){e.urlSync||e.serverPagination?c(t):d(),i.$broadcast("gridReloaded")},e._gridActions.refresh=e.reloadGrid,e._gridActions.filter=e.filter,e._gridActions.sort=e.sort}]).directive("gridItem",["$compile",function(t){return{restrict:"EA",terminal:!0,scope:!1,link:function(e,i,r,n,a){e.serverPagination?i.attr("ng-repeat","item in filtered"):i.attr("ng-repeat","item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage track by $index"),i.removeAttr("grid-item");var o=i[0].outerHTML;i.replaceWith(t(o)(e))}}}]).directive("gridData",["$compile","$animate",function(e){return{restrict:"EA",scope:!0,controller:"gridController",link:function(i,r,n){var a=[],o=r.parent(),s=n.id,c="true"===n.serverPagination;i.serverPagination=c,angular.forEach(angular.element(o[0].querySelectorAll("[sortable]")),function(t){var r=angular.element(t),n=r.attr("sortable");r.attr("ng-class","{'sort-ascent' : sortOptions.predicate ==='"+n+"' && sortOptions.direction === 'asc', 'sort-descent' : sortOptions.predicate === '"+n+"' && sortOptions.direction === 'desc'}"),r.attr("ng-click","sort('"+n+"')"),e(r)(i)}),angular.forEach(document.querySelectorAll("[filter-by]"),function(e){var n=angular.element(e),o=n.attr("filter-by"),c=document.querySelectorAll("[grid-data]")[0],l=c.querySelectorAll('[filter-by="'+o+'"]').length>0,p=n.attr("filter-type")||"",d=n.attr("ng-model"),g=n.attr("disable-url");s&&n.attr("grid-id")&&s!=n.attr("grid-id")||("select"!==p||(i[d+"Options"]=t(i.$eval(r.attr("grid-options")+".data"),o)),!~p.indexOf("date")||n.attr("ng-focus")||n.attr("ng-blur")||(n.attr("ng-focus","filter('{"+d+" : this."+d+"}')"),n.attr("ng-blur","filter('{"+d+" : this."+d+"}')")),d||(d=o,n.attr("ng-model",o),n.attr("ng-change","filter()")),a.push({model:d,isInScope:l,filterBy:o,filterType:p,disableUrl:g}))}),i.filters=a}}}]).factory("filtersFactory",function(){function t(t,e,i){return t.filter(function(t){return!e||!t[i]||t[i]===e})}function e(t,e,i){return t.filter(function(t){return e&&t[i]?~(t[i]+"").toLowerCase().indexOf((e+"").toLowerCase()):!!t[i]})}function i(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return!e||!t[i]||t[i]<=e+86399999})}function r(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return!e||!t[i]||t[i]>=e})}return{getFilterByType:function(n){switch(n){case"select":return t;case"text":return e;case"dateTo":return i;case"dateFrom":return r;default:return null}}}})}(); \ No newline at end of file diff --git a/dist/dataGridUtils.js b/dist/dataGridUtils.js new file mode 100644 index 0000000..06f4061 --- /dev/null +++ b/dist/dataGridUtils.js @@ -0,0 +1,89 @@ +(function () { + 'use strict'; + angular.module('dataGridUtils', []); +})(); +(function () { + 'use strict'; + angular.module('dataGridUtils.fixedHeader', []) + .directive('fixedHeader', FixedHeader); + + FixedHeader.$inject = ['$window', '$timeout']; + + function FixedHeader($window, $timeout) { + var window = angular.element($window); + + return { + restrict: 'A', + link: link + }; + + function link(scope, element, attrs) { + var elementOffsetFrom = attrs.offsetFromElement ? + document.querySelector(attrs.offsetFromElement) : + window; + + function onResize() { + var thElements = element.find("th"); + for (var i = 0; i < thElements.length; i++) { + var tdElement = element.find("td").eq(i)[0]; + if (!tdElement) { + return; + } + var tdElementWidth = tdElement.offsetWidth; + angular.element(thElements[i]).css({'width': tdElementWidth + 'px'}); + } + } + + function bindFixedToHeader() { + var thead = element.find("thead"), + tbody = element.find("tbody"), + tbodyLeftPos = tbody[0].getBoundingClientRect().left; + thead.addClass('fixed-header'); + if (attrs.offsetFromElement) { + var topElement = document.querySelector(attrs.offsetFromElement); + var offset = topElement.getBoundingClientRect().top + topElement.offsetHeight; + thead.css({"top": offset}); + } + thead.css({"left": tbodyLeftPos}); + tbody.addClass("tbody-offset"); + } + + function unBindFixedToHeader() { + var thead = element.find("thead"), + tbody = element.find("tbody"); + thead.removeClass('fixed-header'); + thead.css({"left": ""}); + thead.css({"top": ""}); + tbody.removeClass("tbody-offset"); + } + + function onScroll() { + var offset = attrs.offsetFromElement ? + elementOffsetFrom.getBoundingClientRect().top + elementOffsetFrom.offsetHeight : + $window.pageYOffset, + tableOffsetTop = attrs.offsetFromElement ? + element[0].getBoundingClientRect().top : + element[0].getBoundingClientRect().top + offset, + tableOffsetBottom = tableOffsetTop + element[0].offsetHeight - element.find("thead")[0].offsetHeight; + + if (offset < tableOffsetTop || offset > tableOffsetBottom) { + unBindFixedToHeader(); + } + else if (offset >= tableOffsetTop && offset <= tableOffsetBottom) { + bindFixedToHeader(); + } + onResize(); + } + + scope.$on('gridReloaded', function () { + $timeout(function () { + onResize(); + onScroll(); + }, 0); + }); + window.on('resize', onResize); + window.on('scroll', onScroll); + } + } + +})(); \ No newline at end of file diff --git a/dist/dataGridUtils.min.js b/dist/dataGridUtils.min.js new file mode 100644 index 0000000..fa1410f --- /dev/null +++ b/dist/dataGridUtils.min.js @@ -0,0 +1 @@ +!function(){"use strict";angular.module("dataGridUtils",[])}(),function(){"use strict";function e(e,t){function n(n,f,i){function d(){for(var e=f.find("th"),t=0;to?s():t>=n&&t<=o&&r(),d()}var l=i.offsetFromElement?document.querySelector(i.offsetFromElement):o;n.$on("gridReloaded",function(){t(function(){d(),a()},0)}),o.on("resize",d),o.on("scroll",a)}var o=angular.element(e);return{restrict:"A",link:n}}angular.module("dataGridUtils.fixedHeader",[]).directive("fixedHeader",e),e.$inject=["$window","$timeout"]}(); \ No newline at end of file diff --git a/dist/loading-bar.min.js b/dist/loading-bar.min.js index f0fdc27..2d76439 100644 --- a/dist/loading-bar.min.js +++ b/dist/loading-bar.min.js @@ -1 +1 @@ -!function(){"use strict";angular.module("angular-loading-bar",["cfp.loadingBarInterceptor"]),angular.module("chieffancypants.loadingBar",["cfp.loadingBarInterceptor"]),angular.module("cfp.loadingBarInterceptor",["cfp.loadingBar"]).config(["$httpProvider",function(e){var n=["$q","$cacheFactory","$timeout","$rootScope","$log","cfpLoadingBar",function(n,t,a,r,i,c){function o(){a.cancel(d),c.complete(),u=0,s=0}function l(n){var a,r=t.get("$http"),i=e.defaults;!n.cache&&!i.cache||n.cache===!1||"GET"!==n.method&&"JSONP"!==n.method||(a=angular.isObject(n.cache)?n.cache:angular.isObject(i.cache)?i.cache:r);var c=void 0!==a?void 0!==a.get(n.url):!1;return void 0!==n.cached&&c!==n.cached?n.cached:(n.cached=c,c)}var d,s=0,u=0,g=c.latencyThreshold;return{request:function(e){return e.ignoreLoadingBar||l(e)||(r.$broadcast("cfpLoadingBar:loading",{url:e.url}),0===s&&(d=a(function(){c.start()},g)),s++,c.set(u/s)),e},response:function(e){return e&&e.config?(e.config.ignoreLoadingBar||l(e.config)||(u++,r.$broadcast("cfpLoadingBar:loaded",{url:e.config.url,result:e}),u>=s?o():c.set(u/s)),e):(i.error("Broken interceptor detected: Config object not supplied in response:\n https://github.com/chieffancypants/angular-loading-bar/pull/50"),e)},responseError:function(e){return e&&e.config?(e.config.ignoreLoadingBar||l(e.config)||(u++,r.$broadcast("cfpLoadingBar:loaded",{url:e.config.url,result:e}),u>=s?o():c.set(u/s)),n.reject(e)):(i.error("Broken interceptor detected: Config object not supplied in rejection:\n https://github.com/chieffancypants/angular-loading-bar/pull/50"),n.reject(e))}}}];e.interceptors.push(n)}]),angular.module("cfp.loadingBar",[]).provider("cfpLoadingBar",function(){this.includeSpinner=!0,this.includeBar=!0,this.latencyThreshold=100,this.startSize=.02,this.parentSelector="body",this.spinnerTemplate='
    ',this.loadingBarTemplate='
    ',this.$get=["$injector","$document","$timeout","$rootScope",function(e,n,t,a){function r(){s||(s=e.get("$animate"));var r=n.find(h).eq(0);t.cancel(g),m||(a.$broadcast("cfpLoadingBar:started"),m=!0,b&&s.enter(p,r,angular.element(r[0].lastChild)),$&&s.enter(v,r,angular.element(r[0].lastChild)),i(S))}function i(e){if(m){var n=100*e+"%";f.css("width",n),B=e,t.cancel(u),u=t(function(){c()},250)}}function c(){if(!(o()>=1)){var e=0,n=o();e=n>=0&&.25>n?(3*Math.random()+3)/100:n>=.25&&.65>n?3*Math.random()/100:n>=.65&&.9>n?2*Math.random()/100:n>=.9&&.99>n?.005:0;var t=o()+e;i(t)}}function o(){return B}function l(){B=0,m=!1}function d(){s||(s=e.get("$animate")),a.$broadcast("cfpLoadingBar:completed"),i(1),t.cancel(g),g=t(function(){var e=s.leave(p,l);e&&e.then&&e.then(l),s.leave(v)},500)}var s,u,g,h=this.parentSelector,p=angular.element(this.loadingBarTemplate),f=p.find("div").eq(0),v=angular.element(this.spinnerTemplate),m=!1,B=0,$=this.includeSpinner,b=this.includeBar,S=this.startSize;return{start:r,set:i,status:o,inc:c,complete:d,includeSpinner:this.includeSpinner,latencyThreshold:this.latencyThreshold,parentSelector:this.parentSelector,startSize:this.startSize}}]})}(); \ No newline at end of file +!function(){"use strict";angular.module("angular-loading-bar",["cfp.loadingBarInterceptor"]),angular.module("chieffancypants.loadingBar",["cfp.loadingBarInterceptor"]),angular.module("cfp.loadingBarInterceptor",["cfp.loadingBar"]).config(["$httpProvider",function(e){var n=["$q","$cacheFactory","$timeout","$rootScope","$log","cfpLoadingBar",function(n,t,a,r,i,c){function o(){a.cancel(d),c.complete(),u=0,s=0}function l(n){var a,r=t.get("$http"),i=e.defaults;!n.cache&&!i.cache||n.cache===!1||"GET"!==n.method&&"JSONP"!==n.method||(a=angular.isObject(n.cache)?n.cache:angular.isObject(i.cache)?i.cache:r);var c=void 0!==a&&void 0!==a.get(n.url);return void 0!==n.cached&&c!==n.cached?n.cached:(n.cached=c,c)}var d,s=0,u=0,g=c.latencyThreshold;return{request:function(e){return e.ignoreLoadingBar||l(e)||(r.$broadcast("cfpLoadingBar:loading",{url:e.url}),0===s&&(d=a(function(){c.start()},g)),s++,c.set(u/s)),e},response:function(e){return e&&e.config?(e.config.ignoreLoadingBar||l(e.config)||(u++,r.$broadcast("cfpLoadingBar:loaded",{url:e.config.url,result:e}),u>=s?o():c.set(u/s)),e):(i.error("Broken interceptor detected: Config object not supplied in response:\n https://github.com/chieffancypants/angular-loading-bar/pull/50"),e)},responseError:function(e){return e&&e.config?(e.config.ignoreLoadingBar||l(e.config)||(u++,r.$broadcast("cfpLoadingBar:loaded",{url:e.config.url,result:e}),u>=s?o():c.set(u/s)),n.reject(e)):(i.error("Broken interceptor detected: Config object not supplied in rejection:\n https://github.com/chieffancypants/angular-loading-bar/pull/50"),n.reject(e))}}}];e.interceptors.push(n)}]),angular.module("cfp.loadingBar",[]).provider("cfpLoadingBar",function(){this.includeSpinner=!0,this.includeBar=!0,this.latencyThreshold=100,this.startSize=.02,this.parentSelector="body",this.spinnerTemplate='
    ',this.loadingBarTemplate='
    ',this.$get=["$injector","$document","$timeout","$rootScope",function(e,n,t,a){function r(){s||(s=e.get("$animate"));var r=n.find(h).eq(0);t.cancel(g),m||(a.$broadcast("cfpLoadingBar:started"),m=!0,b&&s.enter(p,r,angular.element(r[0].lastChild)),$&&s.enter(v,r,angular.element(r[0].lastChild)),i(S))}function i(e){if(m){var n=100*e+"%";f.css("width",n),B=e,t.cancel(u),u=t(function(){c()},250)}}function c(){if(!(o()>=1)){var e=0,n=o();e=n>=0&&n<.25?(3*Math.random()+3)/100:n>=.25&&n<.65?3*Math.random()/100:n>=.65&&n<.9?2*Math.random()/100:n>=.9&&n<.99?.005:0;var t=o()+e;i(t)}}function o(){return B}function l(){B=0,m=!1}function d(){s||(s=e.get("$animate")),a.$broadcast("cfpLoadingBar:completed"),i(1),t.cancel(g),g=t(function(){var e=s.leave(p,l);e&&e.then&&e.then(l),s.leave(v)},500)}var s,u,g,h=this.parentSelector,p=angular.element(this.loadingBarTemplate),f=p.find("div").eq(0),v=angular.element(this.spinnerTemplate),m=!1,B=0,$=this.includeSpinner,b=this.includeBar,S=this.startSize;return{start:r,set:i,status:o,inc:c,complete:d,includeSpinner:this.includeSpinner,latencyThreshold:this.latencyThreshold,parentSelector:this.parentSelector,startSize:this.startSize}}]})}(); \ No newline at end of file diff --git a/dist/pagination.min.js b/dist/pagination.min.js index 3dcecb4..eea082a 100644 --- a/dist/pagination.min.js +++ b/dist/pagination.min.js @@ -1 +1 @@ -!function(){"use strict";angular.module("paging",[]).factory("paging",["$parse",function(e){return{create:function(a,n,t){a.setNumPages=t.numPages?e(t.numPages).assign:angular.noop,a.ngModelCtrl={$setViewValue:angular.noop},a.init=function(i,r){a.ngModelCtrl=i,a.config=r,i.$render=function(){a.render()},t.itemsPerPage?n.$parent.$watch(e(t.itemsPerPage),function(e){a.itemsPerPage=parseInt(e,10),n.totalPages=a.calculateTotalPages(),a.updatePage()}):a.itemsPerPage=r.itemsPerPage,n.$watch("totalItems",function(e,t){(angular.isDefined(e)||e!==t)&&(n.totalPages=a.calculateTotalPages(),a.updatePage())})},a.calculateTotalPages=function(){var e=a.itemsPerPage<1?1:Math.ceil(n.totalItems/a.itemsPerPage);return Math.max(e||0,1)},a.render=function(){n.page=parseInt(a.ngModelCtrl.$viewValue,10)||1},n.selectPage=function(e,t){t&&t.preventDefault();var i=!n.ngDisabled||!t;i&&n.page!==e&&e>0&&e<=n.totalPages&&(t&&t.target&&t.target.blur(),a.ngModelCtrl.$setViewValue(e),a.ngModelCtrl.$render())},n.getText=function(e){return n[e+"Text"]||a.config[e+"Text"]},n.noPrevious=function(){return 1===n.page},n.noNext=function(){return n.page===n.totalPages},a.updatePage=function(){a.setNumPages(n.$parent,n.totalPages),n.page>n.totalPages?n.selectPage(n.totalPages):a.ngModelCtrl.$render()}}}}]),angular.module("pagination",["paging"]).controller("PaginationController",["$scope","$attrs","$parse","paging","paginationConfig",function(e,a,n,t,i){function r(e,a,n){return{number:e,text:a,active:n}}function s(e,a){var n=[],t=1,i=a,s=angular.isDefined(g)&&a>g;s&&(o?(t=Math.max(e-Math.floor(g/2),1),i=t+g-1,i>a&&(i=a,t=i-g+1)):(t=(Math.ceil(e/g)-1)*g+1,i=Math.min(t+g-1,a)));for(var l=t;i>=l;l++){var p=r(l,l,l===e);n.push(p)}if(s&&g>0&&(!o||u||c)){if(t>1){if(!c||t>3){var f=r(t-1,"...",!1);n.unshift(f)}if(c){if(3===t){var d=r(2,"2",!1);n.unshift(d)}var P=r(1,"1",!1);n.unshift(P)}}if(a>i){if(!c||a-2>i){var v=r(i+1,"...",!1);n.push(v)}if(c){if(i===a-2){var m=r(a-1,a-1,!1);n.push(m)}var $=r(a,a,!1);n.push($)}}}return n}var l=this,g=angular.isDefined(a.maxSize)?e.$parent.$eval(a.maxSize):i.maxSize,o=angular.isDefined(a.rotate)?e.$parent.$eval(a.rotate):i.rotate,u=angular.isDefined(a.forceEllipses)?e.$parent.$eval(a.forceEllipses):i.forceEllipses,c=angular.isDefined(a.boundaryLinkNumbers)?e.$parent.$eval(a.boundaryLinkNumbers):i.boundaryLinkNumbers;e.boundaryLinks=angular.isDefined(a.boundaryLinks)?e.$parent.$eval(a.boundaryLinks):i.boundaryLinks,e.directionLinks=angular.isDefined(a.directionLinks)?e.$parent.$eval(a.directionLinks):i.directionLinks,t.create(this,e,a),a.maxSize&&e.$parent.$watch(n(a.maxSize),function(e){g=parseInt(e,10),l.render()});var p=this.render;this.render=function(){p(),e.page>0&&e.page<=e.totalPages&&(e.pages=s(e.page,e.totalPages))}}]).constant("paginationConfig",{itemsPerPage:10,boundaryLinks:!1,boundaryLinkNumbers:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0,forceEllipses:!1}).directive("gridPagination",["$parse","paginationConfig",function(e,a){return{scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@",ngDisabled:"="},require:["gridPagination","?ngModel"],controller:"PaginationController",controllerAs:"pagination",templateUrl:function(e,a){return a.templateUrl||"src/template/pagination/pagination.html"},replace:!0,link:function(e,n,t,i){var r=i[0],s=i[1];s&&r.init(s,a)}}}]).run(["$templateCache",function(e){e.put("src/template/pagination/pagination.html","")}])}(); \ No newline at end of file +!function(){"use strict";angular.module("paging",[]).factory("paging",["$parse",function(e){return{create:function(a,n,t){a.setNumPages=t.numPages?e(t.numPages).assign:angular.noop,a.ngModelCtrl={$setViewValue:angular.noop},a.init=function(i,r){a.ngModelCtrl=i,a.config=r,i.$render=function(){a.render()},t.itemsPerPage?n.$parent.$watch(e(t.itemsPerPage),function(e){a.itemsPerPage=parseInt(e,10),n.totalPages=a.calculateTotalPages(),a.updatePage()}):a.itemsPerPage=r.itemsPerPage,n.$watch("totalItems",function(e,t){(angular.isDefined(e)||e!==t)&&(n.totalPages=a.calculateTotalPages(),a.updatePage())})},a.calculateTotalPages=function(){var e=a.itemsPerPage<1?1:Math.ceil(n.totalItems/a.itemsPerPage);return Math.max(e||0,1)},a.render=function(){n.page=parseInt(a.ngModelCtrl.$viewValue,10)||1},n.selectPage=function(e,t){t&&t.preventDefault();var i=!n.ngDisabled||!t;i&&n.page!==e&&e>0&&e<=n.totalPages&&(t&&t.target&&t.target.blur(),a.ngModelCtrl.$setViewValue(e),a.ngModelCtrl.$render())},n.getText=function(e){return n[e+"Text"]||a.config[e+"Text"]},n.noPrevious=function(){return 1===n.page},n.noNext=function(){return n.page===n.totalPages},a.updatePage=function(){a.setNumPages(n.$parent,n.totalPages),n.page>n.totalPages?n.selectPage(n.totalPages):a.ngModelCtrl.$render()}}}}]),angular.module("pagination",["paging"]).controller("PaginationController",["$scope","$attrs","$parse","paging","paginationConfig",function(e,a,n,t,i){function r(e,a,n){return{number:e,text:a,active:n}}function s(e,a){var n=[],t=1,i=a,s=angular.isDefined(g)&&ga&&(i=a,t=i-g+1)):(t=(Math.ceil(e/g)-1)*g+1,i=Math.min(t+g-1,a)));for(var l=t;l<=i;l++){var p=r(l,l,l===e);n.push(p)}if(s&&g>0&&(!o||u||c)){if(t>1){if(!c||t>3){var f=r(t-1,"...",!1);n.unshift(f)}if(c){if(3===t){var d=r(2,"2",!1);n.unshift(d)}var P=r(1,"1",!1);n.unshift(P)}}if(i0&&e.page<=e.totalPages&&(e.pages=s(e.page,e.totalPages))}}]).constant("paginationConfig",{itemsPerPage:10,boundaryLinks:!1,boundaryLinkNumbers:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0,forceEllipses:!1}).directive("gridPagination",["$parse","paginationConfig",function(e,a){return{scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@",ngDisabled:"="},require:["gridPagination","?ngModel"],controller:"PaginationController",controllerAs:"pagination",templateUrl:function(e,a){return a.templateUrl||"src/template/pagination/pagination.html"},replace:!0,link:function(e,n,t,i){var r=i[0],s=i[1];s&&r.init(s,a)}}}]).run(["$templateCache",function(e){e.put("src/template/pagination/pagination.html","")}])}(); \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index d3a2af8..cea1115 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -21,7 +21,7 @@ } gulp.task('js', function () { - gulp.src(['./src/**/*.js']) + gulp.src(['./src/js/vendors/*.js', './src/js/*.js']) .pipe(rename({dirname: ''})) .pipe(gulp.dest('./dist')) .pipe(uglify()) @@ -29,6 +29,15 @@ suffix: ".min" })) .pipe(gulp.dest('./dist')); + + gulp.src(['./src/js/directives/**/*.js']) + .pipe(concat('dataGridUtils.js')) + .pipe(gulp.dest('./dist')) + .pipe(uglify()) + .pipe(rename({ + suffix: ".min" + })) + .pipe(gulp.dest('./dist')); }); gulp.task('sass', function () { @@ -41,6 +50,15 @@ gulp.src('./demo/100k/scss/angular-data-grid.bootstrap.scss') .pipe(sass().on('error', sass.logError)) .pipe(gulp.dest('./demo/100k/css/')); + gulp.src('./demo/fixed-header/scss/fixed-header.bootstrap.scss') + .pipe(sass().on('error', sass.logError)) + .pipe(gulp.dest('./demo/fixed-header/css/')); + gulp.src('./demo/fixed-header/scss/fixed-header.material.scss') + .pipe(sass().on('error', sass.logError)) + .pipe(gulp.dest('./demo/fixed-header/css/')); + gulp.src('./src/js/directives/fixedHeader/fixed-header.scss') + .pipe(sass().on('error', sass.logError)) + .pipe(gulp.dest('./dist/css/fixedHeader/')); }); gulp.task('build', ['js', 'sass']); diff --git a/src/js/dataGrid.js b/src/js/dataGrid.js index 1ae356c..7ed9847 100644 --- a/src/js/dataGrid.js +++ b/src/js/dataGrid.js @@ -12,7 +12,7 @@ return []; } }) - .controller('gridController', ['$scope', '$element', '$filter', '$location', 'filtersFactory', function ($scope, $element, $filter, $location, filtersFactory) { + .controller('gridController', ['$scope', '$rootScope', '$element', '$filter', '$location', 'filtersFactory', function ($scope, $rootScope, $element, $filter, $location, filtersFactory) { // values by default $scope._gridOptions = $scope.$eval($element.attr('grid-options')); $scope._gridActions = $scope.$eval($element.attr('grid-actions')); @@ -84,6 +84,7 @@ } else { applyFilters(); } + $rootScope.$broadcast('gridReloaded'); }; $scope._gridActions.refresh = $scope.reloadGrid; diff --git a/src/js/directives/dataGridUtils.js b/src/js/directives/dataGridUtils.js new file mode 100644 index 0000000..11f7813 --- /dev/null +++ b/src/js/directives/dataGridUtils.js @@ -0,0 +1,4 @@ +(function () { + 'use strict'; + angular.module('dataGridUtils', []); +})(); \ No newline at end of file diff --git a/src/js/directives/fixedHeader/fixed-header.scss b/src/js/directives/fixedHeader/fixed-header.scss new file mode 100644 index 0000000..eeea5eb --- /dev/null +++ b/src/js/directives/fixedHeader/fixed-header.scss @@ -0,0 +1,15 @@ +//Here are described styles that are used bu fixed-header directive +.fixed-header { + top: 0; + position: fixed; + width: auto; + display: table; + z-index: 99; +} + +.tbody-offset { + &:before { + content: " "; + display: block; + } +} \ No newline at end of file diff --git a/src/js/directives/fixedHeader/fixedHeader.js b/src/js/directives/fixedHeader/fixedHeader.js new file mode 100644 index 0000000..8242357 --- /dev/null +++ b/src/js/directives/fixedHeader/fixedHeader.js @@ -0,0 +1,85 @@ +(function () { + 'use strict'; + angular.module('dataGridUtils.fixedHeader', []) + .directive('fixedHeader', FixedHeader); + + FixedHeader.$inject = ['$window', '$timeout']; + + function FixedHeader($window, $timeout) { + var window = angular.element($window); + + return { + restrict: 'A', + link: link + }; + + function link(scope, element, attrs) { + var elementOffsetFrom = attrs.offsetFromElement ? + document.querySelector(attrs.offsetFromElement) : + window; + + function onResize() { + var thElements = element.find("th"); + for (var i = 0; i < thElements.length; i++) { + var tdElement = element.find("td").eq(i)[0]; + if (!tdElement) { + return; + } + var tdElementWidth = tdElement.offsetWidth; + angular.element(thElements[i]).css({'width': tdElementWidth + 'px'}); + } + } + + function bindFixedToHeader() { + var thead = element.find("thead"), + tbody = element.find("tbody"), + tbodyLeftPos = tbody[0].getBoundingClientRect().left; + thead.addClass('fixed-header'); + if (attrs.offsetFromElement) { + var topElement = document.querySelector(attrs.offsetFromElement); + var offset = topElement.getBoundingClientRect().top + topElement.offsetHeight; + thead.css({"top": offset}); + } + thead.css({"left": tbodyLeftPos}); + tbody.addClass("tbody-offset"); + } + + function unBindFixedToHeader() { + var thead = element.find("thead"), + tbody = element.find("tbody"); + thead.removeClass('fixed-header'); + thead.css({"left": ""}); + thead.css({"top": ""}); + tbody.removeClass("tbody-offset"); + } + + function onScroll() { + var offset = attrs.offsetFromElement ? + elementOffsetFrom.getBoundingClientRect().top + elementOffsetFrom.offsetHeight : + $window.pageYOffset, + tableOffsetTop = attrs.offsetFromElement ? + element[0].getBoundingClientRect().top : + element[0].getBoundingClientRect().top + offset, + tableOffsetBottom = tableOffsetTop + element[0].offsetHeight - element.find("thead")[0].offsetHeight; + + if (offset < tableOffsetTop || offset > tableOffsetBottom) { + unBindFixedToHeader(); + } + else if (offset >= tableOffsetTop && offset <= tableOffsetBottom) { + bindFixedToHeader(); + } + onResize(); + } + + scope.$on('gridReloaded', function () { + $timeout(function () { + onResize(); + onScroll(); + }, 0); + }); + window.on('resize', onResize); + window.on('scroll', onScroll); + } + } + +})(); \ No newline at end of file From 647e08141e17f237cddfe7bec6433aefdeed423d Mon Sep 17 00:00:00 2001 From: Andrey Chayko Date: Mon, 10 Apr 2017 13:11:41 +0300 Subject: [PATCH 35/53] Added links to codepen, updated readme.md, added links to additional demos --- README.md | 3 ++- demo/bootstrap/index.html | 3 +++ demo/fixed-header/angular-md-grid.html | 4 ++-- demo/fixed-header/bootstrap-grid.html | 4 ++-- demo/material/index.html | 6 ++++++ 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a453e66..8dc4aab 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,8 @@ Demo Angular UI Router: http://angular-data-grid.github.io/demo/bootstrap/ui-rou - Does not have any hard-coded template so you can choose any mark-up you need, from basic `` layout to any `
    ` structure. - Easily switch between the most popular Bootstrap and Google Material theming, or apply your own CSS theme just by changing several CSS classes. - Built-in sync with browser address bar (URL), so you can copy-n-paste sorting/filtering/pagination results URL and open it in other browser / send to anyone - even if pagination / filtering are done on a client-side. [See details](#url-synchronization) - - Support of [Angular UI Router](https://github.com/angular-ui/ui-router) navigation. + - Support of [Angular UI Router](https://github.com/angular-ui/ui-router) navigation. + - Optional support of fixed header table: [bootstrap Demo](https://github.com/angular-data-grid/demo/fixed-header/bootstrap-grid.html) [Material Design Demo](https://github.com/angular-data-grid/demo/fixed-header/angular-md-grid.html) - Unlike most part of other Angular DataGrids, we intentionally use non-isolated scope of the directive to maximize flexibility, so it can be easily synchronized with any data changes inside your controller. NOTE! With great power comes great responsibility, so use non-isolated API wisely. diff --git a/demo/bootstrap/index.html b/demo/bootstrap/index.html index b0919de..4bbbed7 100644 --- a/demo/bootstrap/index.html +++ b/demo/bootstrap/index.html @@ -48,6 +48,9 @@

    Additional Demos

  • UI Router plus server pagination
  • +
  • + Fixed header table +

  • diff --git a/demo/fixed-header/angular-md-grid.html b/demo/fixed-header/angular-md-grid.html index 134befc..6d47d72 100644 --- a/demo/fixed-header/angular-md-grid.html +++ b/demo/fixed-header/angular-md-grid.html @@ -245,9 +245,9 @@

    Using Stand-alone Directive


    CodePen
    -

    See the Pen eJWWpM by AngularDataGrid (eJWWpM by AngularDataGrid (@AngularDataGrid) on CodePen.

    diff --git a/demo/fixed-header/bootstrap-grid.html b/demo/fixed-header/bootstrap-grid.html index bf2d003..6a13d59 100644 --- a/demo/fixed-header/bootstrap-grid.html +++ b/demo/fixed-header/bootstrap-grid.html @@ -285,8 +285,8 @@

    Additional Demos

    -

    See the Pen xZddZm by AngularDataGrid (@AngularDataGrid) on CodePen.

    +

    See the Pen xZddZm by AngularDataGrid (@AngularDataGrid) on CodePen.

    diff --git a/demo/material/index.html b/demo/material/index.html index 9702465..d14dafa 100644 --- a/demo/material/index.html +++ b/demo/material/index.html @@ -44,6 +44,12 @@

    Angular Data Grid sample using Material Design styling

    Project GitHub

    +

    Additional Demos

    +
    From 9872f03409a7c5c60cbde9b19019fc52f3c31a7a Mon Sep 17 00:00:00 2001 From: Andrey Chayko Date: Mon, 10 Apr 2017 13:16:56 +0300 Subject: [PATCH 36/53] Updated readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8dc4aab..1ea0f5b 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Demo Angular UI Router: http://angular-data-grid.github.io/demo/bootstrap/ui-rou - Easily switch between the most popular Bootstrap and Google Material theming, or apply your own CSS theme just by changing several CSS classes. - Built-in sync with browser address bar (URL), so you can copy-n-paste sorting/filtering/pagination results URL and open it in other browser / send to anyone - even if pagination / filtering are done on a client-side. [See details](#url-synchronization) - Support of [Angular UI Router](https://github.com/angular-ui/ui-router) navigation. - - Optional support of fixed header table: [bootstrap Demo](https://github.com/angular-data-grid/demo/fixed-header/bootstrap-grid.html) [Material Design Demo](https://github.com/angular-data-grid/demo/fixed-header/angular-md-grid.html) + - Optional support of fixed header table: [Bootstrap Demo](http://angular-data-grid.github.io/demo/fixed-header/bootstrap-grid.html) [Material Design Demo](http://angular-data-grid.github.io/demo/fixed-header/angular-md-grid.html) - Unlike most part of other Angular DataGrids, we intentionally use non-isolated scope of the directive to maximize flexibility, so it can be easily synchronized with any data changes inside your controller. NOTE! With great power comes great responsibility, so use non-isolated API wisely. From d8492cd0ecb10a448212cfa78bca9e23f4d8b35e Mon Sep 17 00:00:00 2001 From: Andrey Chayko Date: Mon, 10 Apr 2017 14:37:34 +0300 Subject: [PATCH 37/53] Modified fixed-header sample links structure --- demo/bootstrap/index.html | 2 +- demo/fixed-header/angular-md-grid.html | 21 +++------------ demo/fixed-header/bootstrap-grid.html | 36 ++++---------------------- demo/material/index.html | 2 +- 4 files changed, 10 insertions(+), 51 deletions(-) diff --git a/demo/bootstrap/index.html b/demo/bootstrap/index.html index 4bbbed7..061eb5b 100644 --- a/demo/bootstrap/index.html +++ b/demo/bootstrap/index.html @@ -49,7 +49,7 @@

    Additional Demos

    UI Router plus server pagination
  • - Fixed header table + Fixed header table

  • diff --git a/demo/fixed-header/angular-md-grid.html b/demo/fixed-header/angular-md-grid.html index 6d47d72..d828b6c 100644 --- a/demo/fixed-header/angular-md-grid.html +++ b/demo/fixed-header/angular-md-grid.html @@ -17,30 +17,15 @@
    Angular Data Grid — Material Design - - - - Change theme - arrow_drop_down - - - - - Bootstrap Design - - - Material Design - - - +
    -

    Angular Data Grid sample using Material Design styling

    +

    Fix Header Table

    -

    Features enabled: sorting, filtering, sync with browser URLs, pagination and item-per-page functionality. +

    Features enabled: sorting, filtering, sync with browser URLs, pagination, item-per-page and fixed-header functionality. Out-of-box Angular Material layout and input controls used, along with Material Design Light default CSS for diff --git a/demo/fixed-header/bootstrap-grid.html b/demo/fixed-header/bootstrap-grid.html index 6a13d59..d56420c 100644 --- a/demo/fixed-header/bootstrap-grid.html +++ b/demo/fixed-header/bootstrap-grid.html @@ -14,25 +14,15 @@

    -

    Angular Data Grid sample using out-of-box Bootstrap styling

    - Features enabled: sorting, filtering (using both in-grid and external controls), sync with browser URLs, pagination and items-per-page functionality. +

    Fix Header Table

    + Features enabled: sorting, filtering (using both in-grid and external controls), sync with browser URLs, pagination, items-per-page and fixed-header functionality. Angular UI Datepicker used for date controls, although you can use any other framework, plugin or styling. Project GitHub
    @@ -98,22 +88,6 @@

    Using Stand-alone Directive


    -

    Additional Demos

    - -
    diff --git a/demo/material/index.html b/demo/material/index.html index d14dafa..a9846db 100644 --- a/demo/material/index.html +++ b/demo/material/index.html @@ -47,7 +47,7 @@

    Angular Data Grid sample using Material Design styling

    Additional Demos


    From 616677792f6a671f9ec4e6c4e51d6eee72f4271c Mon Sep 17 00:00:00 2001 From: Igor Korshuk Date: Tue, 11 Apr 2017 16:43:38 +0300 Subject: [PATCH 38/53] #34 reloading the grid after changes in the grid-data --- dist/dataGrid.js | 2 +- dist/dataGrid.min.js | 2 +- src/js/dataGrid.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/dataGrid.js b/dist/dataGrid.js index 7ed9847..14ee687 100644 --- a/dist/dataGrid.js +++ b/dist/dataGrid.js @@ -37,7 +37,7 @@ $scope.customFilters = $scope._gridOptions.customFilters ? angular.copy($scope._gridOptions.customFilters) : {}; $scope.urlSync = $scope._gridOptions.urlSync; - $scope.$watch('_gridOptions.data', function (newValue) { + $scope.$watchCollection('_gridOptions.data', function (newValue) { if (newValue && newValue.length > -1) { $scope.sortCache = {}; $scope.filtered = $scope._gridOptions.data.slice(); diff --git a/dist/dataGrid.min.js b/dist/dataGrid.min.js index 2789310..0aa1794 100644 --- a/dist/dataGrid.min.js +++ b/dist/dataGrid.min.js @@ -1 +1 @@ -!function(){"use strict";function t(t,e){var i=[];if(t)return t.forEach(function(t){~i.indexOf(t[e])||i.push(t[e])}),i.map(function(t){return{text:t,value:t}})}angular.module("dataGrid",[]).filter("startFrom",function(){return function(t,e){return t?(e=+e,t.slice(e)):[]}}).controller("gridController",["$scope","$rootScope","$element","$filter","$location","filtersFactory",function(e,i,r,n,a,o){function s(){(e.urlSync||e.serverPagination)&&(e.serverPagination&&(clearTimeout(e.getDataTimeout),e.getDataTimeout=setTimeout(p,e.getDataDelay)),e.filtered&&l())}function c(t){var i,r=!1;i="page="+e.paginationOptions.currentPage,e.paginationOptions.itemsPerPage!==e.defaultsPaginationOptions.itemsPerPage&&(i+="&itemsPerPage="+e.paginationOptions.itemsPerPage),e.sortOptions.predicate&&(i+="&sort="+encodeURIComponent(e.sortOptions.predicate+"-"+e.sortOptions.direction)),e.filters.forEach(function(t){var n=t.model,a=t.isInScope?e.$eval(n):e.$parent.$eval(n);if(t.disableUrl)return void(r=!0);if(a){var o;if(a instanceof Date){if(isNaN(a.getTime()))return;o=a.getFullYear()+"-",o+=a.getMonth()<9?"0"+(a.getMonth()+1)+"-":a.getMonth()+1+"-",o+=a.getDate()<10?"0"+a.getDate():a.getDate(),a=o}i+="&"+encodeURIComponent(n)+"="+encodeURIComponent(a)}}),r&&d(),a.search(i),t&&e.$apply()}function l(){var t=a.search(),i={};if(Object.keys(t).forEach(function(e){"page"!==e&&"sort"!==e&&"itemsPerPage"!==e&&(i[e]=t[e])}),e.filters.forEach(function(t){var r=t.model,n=i[r];if(!t.disableUrl){if(~t.filterType.toLowerCase().indexOf("date"))return e.$parent.__evaltmp=n?new Date(n):null,void e.$parent.$eval(r+"=__evaltmp");"select"!==t.filterType||n||(n=""),n&&(t.isInScope?(e.__evaltmp=n,e.$eval(r+"=__evaltmp")):(e.$parent.__evaltmp=n,e.$parent.$eval(r+"=__evaltmp")))}}),e.paginationOptions.itemsPerPage=e.defaultsPaginationOptions.itemsPerPage,e.paginationOptions.currentPage=e.defaultsPaginationOptions.currentPage,t.itemsPerPage&&(e.paginationOptions.itemsPerPage=t.itemsPerPage),t.page&&(!e.serverPagination&&(t.page-1)*e.paginationOptions.itemsPerPage>e.filtered.length?e.paginationOptions.currentPage=1:e.paginationOptions.currentPage=t.page),t.sort){var r=t.sort.split("-");e.sortOptions.predicate=decodeURIComponent(r[0]),e.sortOptions.direction=decodeURIComponent(r[1])}e.serverPagination||d()}function p(){var t="",i=a.search();Object.keys(i).forEach(function(e){t+=e+"="+i[e]+"&"}),t=t.slice(0,-1),!t&&e.sortOptions.predicate?e.sort(e.sortOptions.predicate,!0):e._gridOptions.getData("?"+t,function(t,i){e.filtered=t,e.paginationOptions.totalItems=i})}function d(){var t=Date.now(),i=!1;e._time={},e.sortOptions.predicate&&e.sortCache&&e.sortCache.predicate===e.sortOptions.predicate&&e.sortCache.direction===e.sortOptions.direction?(e.filtered=e.sortCache.data.slice(),i=!0):e.filtered=e._gridOptions.data.slice(),e._time.copy=Date.now()-t;var r=Date.now();g(),e._time.filters=Date.now()-r;var a=Date.now();e.sortOptions.predicate&&!i&&(e.filtered=n("orderBy")(e.filtered,e.sortOptions.predicate,"desc"===e.sortOptions.direction),e.sortCache={data:e.filtered.slice(),predicate:e.sortOptions.predicate,direction:e.sortOptions.direction}),e._time.sort=Date.now()-a,e._time.all=Date.now()-t,e.paginationOptions.totalItems=e.filtered.length}function g(){e.filters.forEach(function(t){var i=t.filterBy,r=t.model,n=t.isInScope?e.$eval(r):e.$parent.$eval(r),a=t.filterType;if(e.customFilters[r])e.filtered=e.customFilters[r](e.filtered,n,i);else if(n&&a){var s=o.getFilterByType(a);s&&(e.filtered=s(e.filtered,n,i))}})}e._gridOptions=e.$eval(r.attr("grid-options")),e._gridActions=e.$eval(r.attr("grid-actions")),e.serverPagination="true"===r.attr("server-pagination"),e.getDataDelay=r.attr("get-delay")||350,e._gridActions||(e.$parent.$eval(r.attr("grid-actions")+"= {}"),e._gridActions=e.$parent.$eval(r.attr("grid-actions"))),e._gridOptions.grid=e,e.filtered=e._gridOptions.data.slice(),e.paginationOptions=e._gridOptions.pagination?angular.copy(e._gridOptions.pagination):{},e.defaultsPaginationOptions={itemsPerPage:e.paginationOptions.itemsPerPage||"10",currentPage:e.paginationOptions.currentPage||1},e.paginationOptions=angular.copy(e.defaultsPaginationOptions),e.sortOptions=e._gridOptions.sort?angular.copy(e._gridOptions.sort):{},e.customFilters=e._gridOptions.customFilters?angular.copy(e._gridOptions.customFilters):{},e.urlSync=e._gridOptions.urlSync,e.$watch("_gridOptions.data",function(i){i&&i.length>-1&&(e.sortCache={},e.filtered=e._gridOptions.data.slice(),e.filters.forEach(function(i){"select"===i.filterType&&(e[i.model+"Options"]=t(e.filtered,i.filterBy))}),e.urlSync?l():d())}),e.sort=function(t,i){if(!i){var r=e.sortOptions.predicate===t&&"desc"===e.sortOptions.direction?"asc":"desc";e.sortOptions.direction=r,e.sortOptions.predicate=t}e.paginationOptions.currentPage=1,e.reloadGrid(i)},e.filter=function(){e.paginationOptions.currentPage=1,e.reloadGrid()},e.$on("$locationChangeSuccess",function(){s()}),e.$on("$stateChangeSuccess",function(t,e){s()}),e.reloadGrid=function(t){e.urlSync||e.serverPagination?c(t):d(),i.$broadcast("gridReloaded")},e._gridActions.refresh=e.reloadGrid,e._gridActions.filter=e.filter,e._gridActions.sort=e.sort}]).directive("gridItem",["$compile",function(t){return{restrict:"EA",terminal:!0,scope:!1,link:function(e,i,r,n,a){e.serverPagination?i.attr("ng-repeat","item in filtered"):i.attr("ng-repeat","item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage track by $index"),i.removeAttr("grid-item");var o=i[0].outerHTML;i.replaceWith(t(o)(e))}}}]).directive("gridData",["$compile","$animate",function(e){return{restrict:"EA",scope:!0,controller:"gridController",link:function(i,r,n){var a=[],o=r.parent(),s=n.id,c="true"===n.serverPagination;i.serverPagination=c,angular.forEach(angular.element(o[0].querySelectorAll("[sortable]")),function(t){var r=angular.element(t),n=r.attr("sortable");r.attr("ng-class","{'sort-ascent' : sortOptions.predicate ==='"+n+"' && sortOptions.direction === 'asc', 'sort-descent' : sortOptions.predicate === '"+n+"' && sortOptions.direction === 'desc'}"),r.attr("ng-click","sort('"+n+"')"),e(r)(i)}),angular.forEach(document.querySelectorAll("[filter-by]"),function(e){var n=angular.element(e),o=n.attr("filter-by"),c=document.querySelectorAll("[grid-data]")[0],l=c.querySelectorAll('[filter-by="'+o+'"]').length>0,p=n.attr("filter-type")||"",d=n.attr("ng-model"),g=n.attr("disable-url");s&&n.attr("grid-id")&&s!=n.attr("grid-id")||("select"!==p||(i[d+"Options"]=t(i.$eval(r.attr("grid-options")+".data"),o)),!~p.indexOf("date")||n.attr("ng-focus")||n.attr("ng-blur")||(n.attr("ng-focus","filter('{"+d+" : this."+d+"}')"),n.attr("ng-blur","filter('{"+d+" : this."+d+"}')")),d||(d=o,n.attr("ng-model",o),n.attr("ng-change","filter()")),a.push({model:d,isInScope:l,filterBy:o,filterType:p,disableUrl:g}))}),i.filters=a}}}]).factory("filtersFactory",function(){function t(t,e,i){return t.filter(function(t){return!e||!t[i]||t[i]===e})}function e(t,e,i){return t.filter(function(t){return e&&t[i]?~(t[i]+"").toLowerCase().indexOf((e+"").toLowerCase()):!!t[i]})}function i(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return!e||!t[i]||t[i]<=e+86399999})}function r(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return!e||!t[i]||t[i]>=e})}return{getFilterByType:function(n){switch(n){case"select":return t;case"text":return e;case"dateTo":return i;case"dateFrom":return r;default:return null}}}})}(); \ No newline at end of file +!function(){"use strict";function t(t,e){var i=[];if(t)return t.forEach(function(t){~i.indexOf(t[e])||i.push(t[e])}),i.map(function(t){return{text:t,value:t}})}angular.module("dataGrid",[]).filter("startFrom",function(){return function(t,e){return t?(e=+e,t.slice(e)):[]}}).controller("gridController",["$scope","$rootScope","$element","$filter","$location","filtersFactory",function(e,i,r,n,a,o){function s(){(e.urlSync||e.serverPagination)&&(e.serverPagination&&(clearTimeout(e.getDataTimeout),e.getDataTimeout=setTimeout(p,e.getDataDelay)),e.filtered&&l())}function c(t){var i,r=!1;i="page="+e.paginationOptions.currentPage,e.paginationOptions.itemsPerPage!==e.defaultsPaginationOptions.itemsPerPage&&(i+="&itemsPerPage="+e.paginationOptions.itemsPerPage),e.sortOptions.predicate&&(i+="&sort="+encodeURIComponent(e.sortOptions.predicate+"-"+e.sortOptions.direction)),e.filters.forEach(function(t){var n=t.model,a=t.isInScope?e.$eval(n):e.$parent.$eval(n);if(t.disableUrl)return void(r=!0);if(a){var o;if(a instanceof Date){if(isNaN(a.getTime()))return;o=a.getFullYear()+"-",o+=a.getMonth()<9?"0"+(a.getMonth()+1)+"-":a.getMonth()+1+"-",o+=a.getDate()<10?"0"+a.getDate():a.getDate(),a=o}i+="&"+encodeURIComponent(n)+"="+encodeURIComponent(a)}}),r&&d(),a.search(i),t&&e.$apply()}function l(){var t=a.search(),i={};if(Object.keys(t).forEach(function(e){"page"!==e&&"sort"!==e&&"itemsPerPage"!==e&&(i[e]=t[e])}),e.filters.forEach(function(t){var r=t.model,n=i[r];if(!t.disableUrl){if(~t.filterType.toLowerCase().indexOf("date"))return e.$parent.__evaltmp=n?new Date(n):null,void e.$parent.$eval(r+"=__evaltmp");"select"!==t.filterType||n||(n=""),n&&(t.isInScope?(e.__evaltmp=n,e.$eval(r+"=__evaltmp")):(e.$parent.__evaltmp=n,e.$parent.$eval(r+"=__evaltmp")))}}),e.paginationOptions.itemsPerPage=e.defaultsPaginationOptions.itemsPerPage,e.paginationOptions.currentPage=e.defaultsPaginationOptions.currentPage,t.itemsPerPage&&(e.paginationOptions.itemsPerPage=t.itemsPerPage),t.page&&(!e.serverPagination&&(t.page-1)*e.paginationOptions.itemsPerPage>e.filtered.length?e.paginationOptions.currentPage=1:e.paginationOptions.currentPage=t.page),t.sort){var r=t.sort.split("-");e.sortOptions.predicate=decodeURIComponent(r[0]),e.sortOptions.direction=decodeURIComponent(r[1])}e.serverPagination||d()}function p(){var t="",i=a.search();Object.keys(i).forEach(function(e){t+=e+"="+i[e]+"&"}),t=t.slice(0,-1),!t&&e.sortOptions.predicate?e.sort(e.sortOptions.predicate,!0):e._gridOptions.getData("?"+t,function(t,i){e.filtered=t,e.paginationOptions.totalItems=i})}function d(){var t=Date.now(),i=!1;e._time={},e.sortOptions.predicate&&e.sortCache&&e.sortCache.predicate===e.sortOptions.predicate&&e.sortCache.direction===e.sortOptions.direction?(e.filtered=e.sortCache.data.slice(),i=!0):e.filtered=e._gridOptions.data.slice(),e._time.copy=Date.now()-t;var r=Date.now();g(),e._time.filters=Date.now()-r;var a=Date.now();e.sortOptions.predicate&&!i&&(e.filtered=n("orderBy")(e.filtered,e.sortOptions.predicate,"desc"===e.sortOptions.direction),e.sortCache={data:e.filtered.slice(),predicate:e.sortOptions.predicate,direction:e.sortOptions.direction}),e._time.sort=Date.now()-a,e._time.all=Date.now()-t,e.paginationOptions.totalItems=e.filtered.length}function g(){e.filters.forEach(function(t){var i=t.filterBy,r=t.model,n=t.isInScope?e.$eval(r):e.$parent.$eval(r),a=t.filterType;if(e.customFilters[r])e.filtered=e.customFilters[r](e.filtered,n,i);else if(n&&a){var s=o.getFilterByType(a);s&&(e.filtered=s(e.filtered,n,i))}})}e._gridOptions=e.$eval(r.attr("grid-options")),e._gridActions=e.$eval(r.attr("grid-actions")),e.serverPagination="true"===r.attr("server-pagination"),e.getDataDelay=r.attr("get-delay")||350,e._gridActions||(e.$parent.$eval(r.attr("grid-actions")+"= {}"),e._gridActions=e.$parent.$eval(r.attr("grid-actions"))),e._gridOptions.grid=e,e.filtered=e._gridOptions.data.slice(),e.paginationOptions=e._gridOptions.pagination?angular.copy(e._gridOptions.pagination):{},e.defaultsPaginationOptions={itemsPerPage:e.paginationOptions.itemsPerPage||"10",currentPage:e.paginationOptions.currentPage||1},e.paginationOptions=angular.copy(e.defaultsPaginationOptions),e.sortOptions=e._gridOptions.sort?angular.copy(e._gridOptions.sort):{},e.customFilters=e._gridOptions.customFilters?angular.copy(e._gridOptions.customFilters):{},e.urlSync=e._gridOptions.urlSync,e.$watchCollection("_gridOptions.data",function(i){i&&i.length>-1&&(e.sortCache={},e.filtered=e._gridOptions.data.slice(),e.filters.forEach(function(i){"select"===i.filterType&&(e[i.model+"Options"]=t(e.filtered,i.filterBy))}),e.urlSync?l():d())}),e.sort=function(t,i){if(!i){var r=e.sortOptions.predicate===t&&"desc"===e.sortOptions.direction?"asc":"desc";e.sortOptions.direction=r,e.sortOptions.predicate=t}e.paginationOptions.currentPage=1,e.reloadGrid(i)},e.filter=function(){e.paginationOptions.currentPage=1,e.reloadGrid()},e.$on("$locationChangeSuccess",function(){s()}),e.$on("$stateChangeSuccess",function(t,e){s()}),e.reloadGrid=function(t){e.urlSync||e.serverPagination?c(t):d(),i.$broadcast("gridReloaded")},e._gridActions.refresh=e.reloadGrid,e._gridActions.filter=e.filter,e._gridActions.sort=e.sort}]).directive("gridItem",["$compile",function(t){return{restrict:"EA",terminal:!0,scope:!1,link:function(e,i,r,n,a){e.serverPagination?i.attr("ng-repeat","item in filtered"):i.attr("ng-repeat","item in filtered | startFrom:(paginationOptions.currentPage-1)*paginationOptions.itemsPerPage | limitTo:paginationOptions.itemsPerPage track by $index"),i.removeAttr("grid-item");var o=i[0].outerHTML;i.replaceWith(t(o)(e))}}}]).directive("gridData",["$compile","$animate",function(e){return{restrict:"EA",scope:!0,controller:"gridController",link:function(i,r,n){var a=[],o=r.parent(),s=n.id,c="true"===n.serverPagination;i.serverPagination=c,angular.forEach(angular.element(o[0].querySelectorAll("[sortable]")),function(t){var r=angular.element(t),n=r.attr("sortable");r.attr("ng-class","{'sort-ascent' : sortOptions.predicate ==='"+n+"' && sortOptions.direction === 'asc', 'sort-descent' : sortOptions.predicate === '"+n+"' && sortOptions.direction === 'desc'}"),r.attr("ng-click","sort('"+n+"')"),e(r)(i)}),angular.forEach(document.querySelectorAll("[filter-by]"),function(e){var n=angular.element(e),o=n.attr("filter-by"),c=document.querySelectorAll("[grid-data]")[0],l=c.querySelectorAll('[filter-by="'+o+'"]').length>0,p=n.attr("filter-type")||"",d=n.attr("ng-model"),g=n.attr("disable-url");s&&n.attr("grid-id")&&s!=n.attr("grid-id")||("select"!==p||(i[d+"Options"]=t(i.$eval(r.attr("grid-options")+".data"),o)),!~p.indexOf("date")||n.attr("ng-focus")||n.attr("ng-blur")||(n.attr("ng-focus","filter('{"+d+" : this."+d+"}')"),n.attr("ng-blur","filter('{"+d+" : this."+d+"}')")),d||(d=o,n.attr("ng-model",o),n.attr("ng-change","filter()")),a.push({model:d,isInScope:l,filterBy:o,filterType:p,disableUrl:g}))}),i.filters=a}}}]).factory("filtersFactory",function(){function t(t,e,i){return t.filter(function(t){return!e||!t[i]||t[i]===e})}function e(t,e,i){return t.filter(function(t){return e&&t[i]?~(t[i]+"").toLowerCase().indexOf((e+"").toLowerCase()):!!t[i]})}function i(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return!e||!t[i]||t[i]<=e+86399999})}function r(t,e,i){return e=new Date(e).getTime(),t.filter(function(t){return!e||!t[i]||t[i]>=e})}return{getFilterByType:function(n){switch(n){case"select":return t;case"text":return e;case"dateTo":return i;case"dateFrom":return r;default:return null}}}})}(); \ No newline at end of file diff --git a/src/js/dataGrid.js b/src/js/dataGrid.js index 7ed9847..14ee687 100644 --- a/src/js/dataGrid.js +++ b/src/js/dataGrid.js @@ -37,7 +37,7 @@ $scope.customFilters = $scope._gridOptions.customFilters ? angular.copy($scope._gridOptions.customFilters) : {}; $scope.urlSync = $scope._gridOptions.urlSync; - $scope.$watch('_gridOptions.data', function (newValue) { + $scope.$watchCollection('_gridOptions.data', function (newValue) { if (newValue && newValue.length > -1) { $scope.sortCache = {}; $scope.filtered = $scope._gridOptions.data.slice(); From b69697246e13f379186e8ac806dc0ec3791c01d3 Mon Sep 17 00:00:00 2001 From: AlexZ Date: Tue, 11 Apr 2017 17:22:52 +0300 Subject: [PATCH 39/53] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 1ea0f5b..b20ed11 100644 --- a/README.md +++ b/README.md @@ -248,4 +248,6 @@ Each filter has optional parameter `disable-url` (boolean, default is 'false'). If you need to use 2 or more grids on page, please add `id` to grids, and then use `grid-id` attribute on filters to specify their corresponding grid. [Example](http://angular-data-grid.github.io/demo/bootstrap/multiple.html) ### Next / Future + - Migrate to Heroku + - Cover with unit / e2e tests - Port to Angular2? From 62e58195707e838920c9140970ef56b482adf67d Mon Sep 17 00:00:00 2001 From: Andrey Chayko Date: Wed, 12 Apr 2017 11:47:54 +0300 Subject: [PATCH 40/53] Changed pagination default value for items per page to 75 for both fixed header samples. --- demo/fixed-header/angular-md-grid.html | 4 ++-- demo/fixed-header/bootstrap-grid.html | 4 ++-- demo/fixed-header/js/bootstrap/demoApp.js | 6 +++++- demo/fixed-header/js/material-design/demoApp.js | 6 +++++- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/demo/fixed-header/angular-md-grid.html b/demo/fixed-header/angular-md-grid.html index d828b6c..adac9a9 100644 --- a/demo/fixed-header/angular-md-grid.html +++ b/demo/fixed-header/angular-md-grid.html @@ -156,7 +156,7 @@

    Using Stand-alone Directive

    ng-change="reloadGrid()" items-per-page="paginationOptions.itemsPerPage"> - 10 25 @@ -217,7 +217,7 @@

    Using Stand-alone Directive

    ng-change="reloadGrid()" items-per-page="paginationOptions.itemsPerPage"> - 10 25 diff --git a/demo/fixed-header/bootstrap-grid.html b/demo/fixed-header/bootstrap-grid.html index d56420c..f4b263f 100644 --- a/demo/fixed-header/bootstrap-grid.html +++ b/demo/fixed-header/bootstrap-grid.html @@ -186,7 +186,7 @@

    Using Stand-alone Directive

    - @@ -243,7 +243,7 @@

    Using Stand-alone Directive

    -
    + @@ -94,6 +106,7 @@

    First Grid

    +
    Date Of Birth + +
    @@ -182,6 +195,18 @@

    Second Grid

    Date Of Birth + + + @@ -190,6 +215,7 @@

    Second Grid

    + From 76b4865eb21e4e1063a4f170defd16cbec12209b Mon Sep 17 00:00:00 2001 From: Rowinson Gallego Date: Tue, 15 Aug 2017 09:54:50 -0500 Subject: [PATCH 43/53] Support for ES6 imports was added (#45) --- index.js | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 index.js diff --git a/index.js b/index.js new file mode 100644 index 0000000..6b85ad2 --- /dev/null +++ b/index.js @@ -0,0 +1,7 @@ +require('./dist/dataGrid'); +require('./dist/pagination'); + +module.exports = { + dataGrid: 'dataGrid', + pagination: 'pagination', +}; diff --git a/package.json b/package.json index 260e070..9aaf0b6 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "gulp-uglify": "^1.4.2" }, "description": "Light, flexible and performant Data Grid for AngularJS apps, with built-in sorting, pagination and filtering options, unified API for client-side and server-side data fetching, \r seamless synchronization with browser address bar and total freedom in mark-up and styling suitable for your application. Angular 1.3 - 1.6 compliant.", - "main": "index.html", + "main": "index.js", "devDependencies": {}, "repository": { "type": "git", From 52db8e025d4648a21c9a083242e1b914c7e0f762 Mon Sep 17 00:00:00 2001 From: Andrey Chayko Date: Wed, 16 Aug 2017 18:46:27 +0300 Subject: [PATCH 44/53] Updated samples for material design. Fixed sorting icons display issue for IE. Fixed content alignment for fixed header sample --- demo/fixed-header/angular-md-grid.html | 388 +++++++++--------- .../css/angular-data-grid.material.css | 42 +- demo/material/index.html | 46 ++- .../scss/angular-data-grid.material.scss | 44 +- .../scss/angular-data-grid.variables.scss | 3 +- 5 files changed, 251 insertions(+), 272 deletions(-) diff --git a/demo/fixed-header/angular-md-grid.html b/demo/fixed-header/angular-md-grid.html index 96aeb30..46dfd74 100644 --- a/demo/fixed-header/angular-md-grid.html +++ b/demo/fixed-header/angular-md-grid.html @@ -21,34 +21,35 @@
    -
    -
    -

    Fix Header Table

    +
    +
    +
    +

    Fix Header Table

    -

    Features enabled: sorting, filtering, sync with browser URLs, pagination, item-per-page and fixed-header functionality. - Out-of-box Angular Material layout and - input controls used, - along with Material Design Light default CSS for - grid styling. - Project GitHub

    +

    Features enabled: sorting, filtering, sync with browser URLs, pagination, item-per-page and fixed-header functionality. + Out-of-box Angular Material layout and + input controls used, + along with Material Design Light default CSS for + grid styling. + Project GitHub

    -
    -

    How To Freeze Table Header

    -

    Using HTML Layout

    -
    -

    The first option is to split table header and table body in two tables. - One way to do this is to follow the next steps:

    -
      -
    • Use the next styles (with any fixed height) applied to table body container to make it scrollable:
      - .div-table-body { height: 600px; overflow-x: auto; overflow-y: scroll; }
      -
    • -
    • Make sure that th elements have the same padding as td elements have.
    • -
    • Use padding-right with the value of scroll bar width to make an offset for the table contains header.
    • -
    • Use width attribute for columns to sync widths.
    • -
    -

    Code Sample: -

    +                
    +

    How To Freeze Table Header

    +

    Using HTML Layout

    +
    +

    The first option is to split table header and table body in two tables. + One way to do this is to follow the next steps:

    +
      +
    • Use the next styles (with any fixed height) applied to table body container to make it scrollable:
      + .div-table-body { height: 600px; overflow-x: auto; overflow-y: scroll; }
      +
    • +
    • Make sure that th elements have the same padding as td elements have.
    • +
    • Use padding-right with the value of scroll bar width to make an offset for the table contains header.
    • +
    • Use width attribute for columns to sync widths.
    • +
    +

    Code Sample: +

     <table>
         <thead>
             ...
    @@ -60,182 +61,187 @@ 

    Using HTML Layout

    </tbody> </table>
    -

    -
    -

    Using Stand-alone Directive

    -
    -

    Another option is to use the directive fixed-header that can be injected to the Data Grid like a separate module dataGridUtils.

    -

    To make it work it is needed to perform next steps:

    -
      -
    • Include script to your application:
      - <script src="bower_components/angular-data-grid/dist/dataGridUtils.min.js"></script> -
    • -
    • Include css stylesheets to your application:
      - <link rel="stylesheet" href="bower_components/angular-data-grid/css/fixedHeader/fixed-header.css"> -
    • -
    • Inject dataGridUtils dependency in your module:
      - angular.module('myApp', ['dataGrid', 'dataGridUtils.fixedHeader']) -
    • -
    • Apply the directive fixed-header to the grid table:
      - <table class="table" fixed-header> -
    • -
    -

    The directive uses z-index: 99 if your page uses the same value or higher please make appropriate changes to fixed-header.scss file.

    -

    The directive also has additional attribute offset-from-element. - It is needed if you already have some other elements with fixed position above the table. - In this case you need to pass a class or id of the very last element (if there are several) to this attribute - to make the directive take - into consideration that header needs to be fixed with offset from above elements.

    -

    Example:
    +

    +
    +

    Using Stand-alone Directive

    +
    +

    Another option is to use the directive fixed-header that can be injected to the Data Grid like a separate module dataGridUtils.

    +

    To make it work it is needed to perform next steps:

    +
      +
    • Include script to your application:
      + <script src="bower_components/angular-data-grid/dist/dataGridUtils.min.js"></script> +
    • +
    • Include css stylesheets to your application:
      + <link rel="stylesheet" href="bower_components/angular-data-grid/css/fixedHeader/fixed-header.css"> +
    • +
    • Inject dataGridUtils dependency in your module:
      + angular.module('myApp', ['dataGrid', 'dataGridUtils.fixedHeader']) +
    • +
    • Apply the directive fixed-header to the grid table:
      + <table class="table" fixed-header> +
    • +
    +

    The directive uses z-index: 99 if your page uses the same value or higher please make appropriate changes to fixed-header.scss file.

    +

    The directive also has additional attribute offset-from-element. + It is needed if you already have some other elements with fixed position above the table. + In this case you need to pass a class or id of the very last element (if there are several) to this attribute + to make the directive take + into consideration that header needs to be fixed with offset from above elements.

    +

    Example:

    <table class="table" fixed-header offset-from-element=".the-class-on-above-fixed-element">
    or
    <table class="table" fixed-header offset-from-element="#the-id-on-above-fixed-element”>
    -

    -
    -

    The directive subscribes on scroll event, but the event is not fired when directive is used inside <md-content>, so to make it work please use the directive outside the <md-content> container. - For more information about this problem please review this issue. -

    +

    +
    +

    The directive subscribes on scroll event, but the event is not fired when directive is used inside <md-content>, so to make it work please use the directive + outside the <md-content> container. + For more information about this problem please review this issue. +

    +

    -
    -
    -
    -
    - - - -
    -
    - -
    -
    - -
    -
    - Clear Dates - -
    -
    -
    -
    -
    - {{filtered.length}} items total +
    +
    + + +
    -
    -
    - - - - 10 - 25 - 50 - 75 - - -
    +
    + + +
    +
    + + +
    +
    + Clear Dates +
    -
    - - - - - - - - - - - - - - - - - -
    - Order # - - - All Statuses - - {{option.text}} - - - - Date Placed - - Total -
    - -
    +
    +
    +
    + {{filtered.length}} items total +
    +
    +
    + + + + 10 + 25 + 50 + 75 + + +
    +
    +
    +
    + + + + + + + + + + + + + + + + + +
    + Order # + + + + All Statuses + + {{option.text}} + + + + Date Placed + + + Total + +
    + +
    +
    +
    + + + + 10 + 25 + 50 + 75 + + +
    -
    - - - - 10 - 25 - 50 - 75 - - +
    + CodePen +
    +

    See the Pen eJWWpM by AngularDataGrid (@AngularDataGrid) on CodePen. +

    +
    +
    -
    - CodePen -
    -

    See the Pen eJWWpM by AngularDataGrid (@AngularDataGrid) on CodePen. -

    - -
    -
    diff --git a/demo/material/css/angular-data-grid.material.css b/demo/material/css/angular-data-grid.material.css index 7e6dc66..7edbd95 100644 --- a/demo/material/css/angular-data-grid.material.css +++ b/demo/material/css/angular-data-grid.material.css @@ -51,33 +51,19 @@ th md-select { .pagination-page.active a { color: #fff; } -.material-icons, .sortable span:before, .sortable span:after { - font-family: 'Material Icons'; - font-size: 18px; - -webkit-font-feature-settings: 'liga'; - -webkit-font-smoothing: antialiased; } +.sortable .arrow { + position: relative; + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; } -.sortable span { - position: relative; } - .sortable span:before { - content: 'arrow_drop_down'; - position: absolute; - right: -18px; - top: -2px; } - .sortable span:after { - content: 'arrow_drop_up'; - position: absolute; - right: -18px; - top: -9px; } +.sortable.sort-ascent .arrow { + top: -10px; + left: 5px; + border-bottom: 4px solid #757575; } -.sortable.sort-ascent span:before { - display: none; } - -.sortable.sort-ascent span:after { - top: -5px; } - -.sortable.sort-descent span:before { - top: -5px; } - -.sortable.sort-descent span:after { - display: none; } +.sortable.sort-descent .arrow { + top: 10px; + left: 5px; + border-top: 4px solid #757575; } diff --git a/demo/material/index.html b/demo/material/index.html index a9846db..b457c91 100644 --- a/demo/material/index.html +++ b/demo/material/index.html @@ -14,7 +14,6 @@
    Angular Data Grid — Material Design - @@ -33,17 +32,15 @@
    - +
    -
    -

    Angular Data Grid sample using Material Design styling

    +

    Angular Data Grid sample using Material Design styling

    -

    Features enabled: sorting, filtering, sync with browser URLs, pagination and item-per-page functionality. - Out-of-box Angular Material layout and input controls used, - along with Material Design Light default CSS for grid styling. - Project GitHub

    -
    +

    Features enabled: sorting, filtering, sync with browser URLs, pagination and item-per-page functionality. + Out-of-box Angular Material layout and input controls used, + along with Material Design Light default CSS for grid styling. + Project GitHub

    Additional Demos

    • @@ -51,9 +48,10 @@

      Additional Demos


    +
    -
    - +
    + Additional Demos aria-invalid="false">
    -
    +
    + ng-change="gridActions.filter()"> +
    -
    +
    + ng-change="gridActions.filter()"> +
    -
    - Clear Dates +
    + Clear Dates +
    @@ -120,6 +121,7 @@

    Additional Demos

    Order # + Additional Demos Date Placed + Total + @@ -183,7 +187,7 @@

    Additional Demos


    - +
    diff --git a/demo/material/scss/angular-data-grid.material.scss b/demo/material/scss/angular-data-grid.material.scss index ff688a7..fdb8d81 100644 --- a/demo/material/scss/angular-data-grid.material.scss +++ b/demo/material/scss/angular-data-grid.material.scss @@ -64,44 +64,26 @@ th md-select { } } } -.material-icons { - font-family: 'Material Icons'; - font-size: 18px; - -webkit-font-feature-settings: 'liga'; - -webkit-font-smoothing: antialiased; -} .sortable { - span { + .arrow { position: relative; - &:before { - @extend .material-icons; - content: 'arrow_drop_down'; - position: absolute; - right: -18px; - top: -2px; - } - &:after { - @extend .material-icons; - content: 'arrow_drop_up'; - position: absolute; - right: -18px; - top: -9px; - } + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; } &.sort-ascent { - span:before { - display: none; - } - span:after { - top: -5px + .arrow { + top: -10px; + left: 5px; + border-bottom: 4px solid $backgroundArrows; } } &.sort-descent { - span:before { - top: -5px - } - span:after { - display: none; + .arrow { + top: 10px; + left: 5px; + border-top: 4px solid $backgroundArrows; } } } \ No newline at end of file diff --git a/demo/material/scss/angular-data-grid.variables.scss b/demo/material/scss/angular-data-grid.variables.scss index 60b1dda..2c7053a 100644 --- a/demo/material/scss/angular-data-grid.variables.scss +++ b/demo/material/scss/angular-data-grid.variables.scss @@ -2,4 +2,5 @@ $backgroundActive: rgb(63, 81, 181); $foregroundActive: #fff; $foregroundPagination: #ddd; $foregroundDefault: #444; -$backgroundIcons: #333; \ No newline at end of file +$backgroundIcons: #333; +$backgroundArrows: #757575; \ No newline at end of file From 4b2ace651c087bceac8952b49127c0ad739b219d Mon Sep 17 00:00:00 2001 From: Andrey Chayko Date: Thu, 17 Aug 2017 15:07:28 +0300 Subject: [PATCH 45/53] Updated angular material version to 1.1.4 and material design lite to version 1.3.0 --- demo/fixed-header/angular-md-grid.html | 22 +++++++++++----------- demo/material/index.html | 22 +++++++++++----------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/demo/fixed-header/angular-md-grid.html b/demo/fixed-header/angular-md-grid.html index 46dfd74..78f4215 100644 --- a/demo/fixed-header/angular-md-grid.html +++ b/demo/fixed-header/angular-md-grid.html @@ -5,8 +5,8 @@ Angular Data Grid - Fix Header Table - - + + @@ -158,10 +158,10 @@

    Using Stand-alone Directive

    - 10 - 25 - 50 - 75 + 10 + 25 + 50 + 75
    @@ -222,10 +222,10 @@

    Using Stand-alone Directive

    - 10 - 25 - 50 - 75 + 10 + 25 + 50 + 75
    @@ -250,7 +250,7 @@

    Using Stand-alone Directive

    - + diff --git a/demo/material/index.html b/demo/material/index.html index b457c91..76acecd 100644 --- a/demo/material/index.html +++ b/demo/material/index.html @@ -5,8 +5,8 @@ Angular Data Grid - Material Design - - + + @@ -106,10 +106,10 @@

    Additional Demos

    items-per-page="paginationOptions.itemsPerPage"> - 10 - 25 - 50 - 75 + 10 + 25 + 50 + 75
    @@ -169,10 +169,10 @@

    Additional Demos

    items-per-page="paginationOptions.itemsPerPage"> - 10 - 25 - 50 - 75 + 10 + 25 + 50 + 75
    @@ -195,7 +195,7 @@

    Additional Demos

    - + From fa133e63aa54fc8260d445f19f69978c40452498 Mon Sep 17 00:00:00 2001 From: Alexander Zhuk Date: Thu, 17 Aug 2017 15:30:43 +0300 Subject: [PATCH 46/53] Export grid data #54 fix - feature added --- README.md | 1 + demo/bootstrap/index.html | 32 +- demo/bootstrap/js/demoApp.js | 15 +- demo/data.json | 1907 ++++++++++---------------- dist/JSONToCSVConvertor.js | 84 ++ src/js/vendors/JSONToCSVConvertor.js | 84 ++ 6 files changed, 956 insertions(+), 1167 deletions(-) create mode 100644 dist/JSONToCSVConvertor.js create mode 100644 src/js/vendors/JSONToCSVConvertor.js diff --git a/README.md b/README.md index b20ed11..b1dc410 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Demo Angular UI Router: http://angular-data-grid.github.io/demo/bootstrap/ui-rou - Built-in sync with browser address bar (URL), so you can copy-n-paste sorting/filtering/pagination results URL and open it in other browser / send to anyone - even if pagination / filtering are done on a client-side. [See details](#url-synchronization) - Support of [Angular UI Router](https://github.com/angular-ui/ui-router) navigation. - Optional support of fixed header table: [Bootstrap Demo](http://angular-data-grid.github.io/demo/fixed-header/bootstrap-grid.html) [Material Design Demo](http://angular-data-grid.github.io/demo/fixed-header/angular-md-grid.html) + - Optional support of CSV data exports: [Demo](http://angular-data-grid.github.io/demo/bootstrap/) - Unlike most part of other Angular DataGrids, we intentionally use non-isolated scope of the directive to maximize flexibility, so it can be easily synchronized with any data changes inside your controller. NOTE! With great power comes great responsibility, so use non-isolated API wisely. diff --git a/demo/bootstrap/index.html b/demo/bootstrap/index.html index 061eb5b..fecbd10 100644 --- a/demo/bootstrap/index.html +++ b/demo/bootstrap/index.html @@ -30,7 +30,8 @@

    Angular Data Grid sample using out-of-box Bootstrap styling

    - Features enabled: sorting, filtering (using both in-grid and external controls), sync with browser URLs, pagination and items-per-page functionality. + Features enabled: sorting, filtering (using both in-grid and external controls), sync with browser URLs, + pagination and items-per-page functionality, plus optional plugin for CSV exports. Angular UI Datepicker used for date controls, although you can use any other framework, plugin or styling. Project GitHub
    @@ -88,7 +89,7 @@

    Additional Demos

    ng-focus="gridActions.filter()" show-weeks="false" close-text="Close"/> - + @@ -118,7 +119,7 @@

    Additional Demos

    ng-focus="gridActions.filter()" show-weeks="false" close-text="Close"> - + @@ -131,6 +132,13 @@

    Additional Demos


    +
    + + +
    +
    @@ -151,7 +159,9 @@

    Additional Demos

    - @@ -208,7 +218,8 @@

    Additional Demos

    -