Comparing version 0.3.2 to 0.5.4
{ | ||
"name": "ng-table", | ||
"version": "0.3.2", | ||
"version": "0.5.3", | ||
"main": [ | ||
"ng-table.js", | ||
"ng-table.css" | ||
"./dist/ng-table.min.js", | ||
"./dist/ng-table.min.css" | ||
], | ||
@@ -8,0 +8,0 @@ "ignore": [ |
CONTRIBUTING | ||
============ | ||
Here's a quick guide: | ||
1. Fork the repo. | ||
@@ -12,10 +10,18 @@ | ||
4. Run the tests: `karma start` | ||
4. Run the build: `grunt` | ||
- builds dist/ng-table.js and associated files | ||
5. Make changes in source folder `src`. | ||
5. Run the tests: `karma start` | ||
- ie prove existing code before making your changes | ||
6. Make changes in source folder (`src`) | ||
6. Minify source files: `grunt` | ||
7. Make the test pass. | ||
7. Make the test pass | ||
8. Push to your fork and submit a pull request. | ||
8. Commit changes: | ||
- include ONLY source files ie do NOT commit files under the dist/ folder | ||
- use a commit message that follows [conventions](https://github.com/ajoslin/conventional-changelog/blob/master/CONVENTIONS.md) | ||
9. Push your changes to your fork and submit a pull request |
@@ -8,3 +8,3 @@ define([ | ||
var app = angular.module('main', ['ngTable']). | ||
controller('DemoCtrl', function($scope, $filter, $q, ngTableParams) { | ||
controller('DemoCtrl', function($scope, $filter, $q, NgTableParams) { | ||
var data = [{name: "Moroni", age: 50, money: -10}, | ||
@@ -28,3 +28,3 @@ {name: "Tiancum", age: 43,money: 120}, | ||
$scope.tableParams = new ngTableParams({ | ||
$scope.tableParams = new NgTableParams({ | ||
$liveFiltering: true, | ||
@@ -55,6 +55,6 @@ page: 1, // show first page | ||
// use build-in angular filter | ||
var orderedData = params.sorting ? | ||
var orderedData = params.sorting ? | ||
$filter('orderBy')(data, params.orderBy()) : | ||
data; | ||
orderedData = params.filter ? | ||
orderedData = params.filter ? | ||
$filter('filter')(orderedData, params.filter) : | ||
@@ -68,2 +68,2 @@ orderedData; | ||
return app; | ||
}); | ||
}); |
@@ -5,17 +5,17 @@ require.config({ | ||
angular: '../js/angular.min', | ||
ngTable: '../../ng-table' | ||
ngTable: '../../dist' | ||
}, | ||
shim: { | ||
'angular' : {'exports' : 'angular'} | ||
'angular': {'exports': 'angular'} | ||
} | ||
}); | ||
require( [ | ||
require([ | ||
'jquery', | ||
'angular', | ||
'app' | ||
], function($, angular, app) { | ||
], function ($, angular, app) { | ||
'use strict'; | ||
angular.bootstrap(document, ['main']); | ||
}); | ||
}); |
@@ -1,5 +0,5 @@ | ||
var mountFolder = function (connect, dir) { | ||
var mountFolder = function(connect, dir) { | ||
return connect.static(require('path').resolve(dir)); | ||
}; | ||
module.exports = function (grunt) { | ||
module.exports = function(grunt) { | ||
@@ -20,3 +20,3 @@ require('load-grunt-tasks')(grunt); | ||
'dev', | ||
'uglify', | ||
'uglify', | ||
'cssmin' | ||
@@ -37,8 +37,6 @@ ]); | ||
styles: { | ||
files: [ | ||
{ | ||
src: './src/styles/ng-table.less', | ||
dest: './ng-table.less' | ||
} | ||
] | ||
files: [{ | ||
src: './src/styles/ng-table.less', | ||
dest: './dist/ng-table.less' | ||
}] | ||
} | ||
@@ -48,9 +46,7 @@ }, | ||
js: { | ||
src: ['ng-table.js'], | ||
dest: 'ng-table.min.js', | ||
src: ['./dist/ng-table.js'], | ||
dest: './dist/ng-table.min.js', | ||
options: { | ||
banner: '<%= banner %>', | ||
sourceMap: function (fileName) { | ||
return fileName.replace(/\.min\.js$/, '.map'); | ||
} | ||
sourceMap: true | ||
} | ||
@@ -71,3 +67,3 @@ } | ||
], | ||
dest: 'ng-table.js' | ||
dest: './dist/ng-table.js' | ||
} | ||
@@ -78,3 +74,3 @@ }, | ||
files: { | ||
'ng-table.css': 'src/styles/ng-table.less' | ||
'./dist/ng-table.css': 'src/styles/ng-table.less' | ||
} | ||
@@ -86,3 +82,3 @@ } | ||
files: { | ||
'ng-table.min.css': 'ng-table.css' | ||
'./dist/ng-table.min.css': './dist/ng-table.css' | ||
}, | ||
@@ -124,3 +120,3 @@ options: { | ||
options: { | ||
middleware: function (connect) { | ||
middleware: function(connect) { | ||
return [ | ||
@@ -145,2 +141,2 @@ mountFolder(connect, '.') | ||
}); | ||
}; | ||
}; |
@@ -16,3 +16,3 @@ // Karma configuration file | ||
// directive | ||
'ng-table.js', | ||
'./dist/ng-table.js', | ||
@@ -19,0 +19,0 @@ // tests |
{ | ||
"name": "ng-table", | ||
"version": "0.3.2", | ||
"version": "0.5.4", | ||
"author": "Vitalii Savchuk <esvit666@gmail.com>", | ||
@@ -11,26 +11,24 @@ "license": "BSD", | ||
"devDependencies": { | ||
"coffee-script": "~1.6.2", | ||
"grunt-regarde": "~0.1.1", | ||
"grunt-contrib-jade": "~0.5.0", | ||
"grunt-hustler": "0.11.2", | ||
"grunt-contrib-copy": "~0.4.1", | ||
"coveralls": "~2.11.0", | ||
"grunt": "~0.4.2", | ||
"grunt-contrib-clean": "~0.4.0", | ||
"grunt-contrib-coffee": "~0.7.0", | ||
"grunt-contrib-clean": "~0.4.0", | ||
"grunt-contrib-concat": "~0.3.0", | ||
"grunt-contrib-requirejs": "~0.4.0", | ||
"grunt-contrib-uglify": "~0.2.1", | ||
"grunt-contrib-connect": "~0.5.0", | ||
"grunt": "~0.4.2", | ||
"grunt-contrib-copy": "~0.4.1", | ||
"grunt-contrib-cssmin": "~0.6.1", | ||
"grunt-contrib-jade": "~0.5.0", | ||
"grunt-contrib-less": "~0.5.2", | ||
"grunt-contrib-cssmin": "~0.6.1", | ||
"grunt-contrib-requirejs": "~0.4.0", | ||
"grunt-contrib-uglify": "0.8.x", | ||
"grunt-contrib-watch": "~0.6.x", | ||
"grunt-hustler": "0.11.2", | ||
"karma": "~0.12.0", | ||
"karma-chrome-launcher": "~0.1.0", | ||
"karma-coverage": "~0.2.0", | ||
"karma-firefox-launcher": "~0.1.0", | ||
"karma-jasmine": "~0.1.0", | ||
"karma-ng-html2js-preprocessor": "~0.1.0", | ||
"load-grunt-tasks": "~0.2.0", | ||
"grunt-contrib-watch": "~0.5.3", | ||
"karma": "~0.10", | ||
"karma-jasmine": "*", | ||
"karma-chrome-launcher": "*", | ||
"karma-firefox-launcher": "*", | ||
"karma-ng-html2js-preprocessor": "*", | ||
"coveralls": "", | ||
"karma-coverage": "~0.1.0", | ||
"grunt-coffee-build": "~1.4.12" | ||
"qq": "^0.3.5" | ||
}, | ||
@@ -37,0 +35,0 @@ "scripts": { |
@@ -25,34 +25,5 @@ Table + AngularJS | ||
### v0.3.2 (master) | ||
- add pagination directive ngTablePagination [(see usage)](https://github.com/esvit/ng-table/blob/master/examples/demo28.html) | ||
- rename filter.name to filter.$$name according to issue #196 | ||
- add debugMode setting | ||
- add defaultSort setting | ||
- add filterDelay setting | ||
- add multisorting (click on header with Ctrl-key) | ||
- add css classes (ng-table-pager, ng-table-pagination, ng-table-counts) | ||
See CHANGELOG.md | ||
### v0.3.1 | ||
- add support of `header-class` attribute | ||
- add fixes for compatibility with early versions of AngularJS | ||
- add `data` field to ngTableParams | ||
- Allow expressions in the sortable & filter attribute (Issue #93) | ||
### v0.3.0 | ||
- I abandoned from CoffeeScript in favor of a javascript, fully agree with http://blog.ponyfoo.com/2013/09/28/we-dont-want-your-coffee & (rus) http://habrahabr.ru/post/195944/ | ||
- added examples of table with grouping | ||
- fully rewrited interface of ngTableParams | ||
### v0.2.2 | ||
In functions that return data for the filters were removed `.promise` | ||
```javascript | ||
$scope.names = function(column) { | ||
... | ||
def.resolve(names); | ||
// return def.promise; - old code | ||
return def; | ||
}; | ||
``` | ||
## Installing via Bower | ||
@@ -93,3 +64,3 @@ ``` | ||
## Configuring ng-table | ||
For a list of configuration options available, see [Configuring your table with ngTableParams](https://github.com/esvit/ng-table/wiki/Configuring-your-table-with-ngTableParams) | ||
For a list of configuration options available, see [Configuring your table with NgTableParams](https://github.com/esvit/ng-table/wiki/Configuring-your-table-with-ngTableParams) | ||
@@ -96,0 +67,0 @@ #### PS |
@@ -11,3 +11,3 @@ (function(angular, factory) { | ||
} | ||
}(angular || null, function(angular) { | ||
'use strict'; | ||
}(window.angular || null, function(angular) { | ||
'use strict'; |
@@ -10,13 +10,24 @@ /** | ||
/** | ||
* @ngdoc value | ||
* @name ngTable.value:ngTableDefaultParams | ||
* @description Default Parameters for ngTable | ||
*/ | ||
app.value('ngTableDefaults', { | ||
params: {}, | ||
settings: {} | ||
}); | ||
/** | ||
* @ngdoc service | ||
* @name ngTable.factory:ngTableParams | ||
* @name ngTable.factory:NgTableParams | ||
* @description Parameters manager for ngTable | ||
*/ | ||
app.factory('ngTableParams', ['$q', '$log', function ($q, $log) { | ||
var isNumber = function (n) { | ||
app.factory('NgTableParams', ['$q', '$log', 'ngTableDefaults', function($q, $log, ngTableDefaults) { | ||
var isNumber = function(n) { | ||
return !isNaN(parseFloat(n)) && isFinite(n); | ||
}; | ||
var ngTableParams = function (baseParameters, baseSettings) { | ||
var NgTableParams = function(baseParameters, baseSettings) { | ||
var self = this, | ||
log = function () { | ||
log = function() { | ||
if (settings.debugMode && $log.debug) { | ||
@@ -31,4 +42,4 @@ $log.debug.apply(this, arguments); | ||
* @ngdoc method | ||
* @name ngTable.factory:ngTableParams#parameters | ||
* @methodOf ngTable.factory:ngTableParams | ||
* @name ngTable.factory:NgTableParams#parameters | ||
* @methodOf ngTable.factory:NgTableParams | ||
* @description Set new parameters or get current parameters | ||
@@ -40,3 +51,3 @@ * | ||
*/ | ||
this.parameters = function (newParameters, parseParamsFromUrl) { | ||
this.parameters = function(newParameters, parseParamsFromUrl) { | ||
parseParamsFromUrl = parseParamsFromUrl || false; | ||
@@ -73,4 +84,4 @@ if (angular.isDefined(newParameters)) { | ||
* @ngdoc method | ||
* @name ngTable.factory:ngTableParams#settings | ||
* @methodOf ngTable.factory:ngTableParams | ||
* @name ngTable.factory:NgTableParams#settings | ||
* @methodOf ngTable.factory:NgTableParams | ||
* @description Set new settings for table | ||
@@ -81,3 +92,3 @@ * | ||
*/ | ||
this.settings = function (newSettings) { | ||
this.settings = function(newSettings) { | ||
if (angular.isDefined(newSettings)) { | ||
@@ -97,4 +108,4 @@ if (angular.isArray(newSettings.data)) { | ||
* @ngdoc method | ||
* @name ngTable.factory:ngTableParams#page | ||
* @methodOf ngTable.factory:ngTableParams | ||
* @name ngTable.factory:NgTableParams#page | ||
* @methodOf ngTable.factory:NgTableParams | ||
* @description If parameter page not set return current page else set current page | ||
@@ -105,4 +116,6 @@ * | ||
*/ | ||
this.page = function (page) { | ||
return angular.isDefined(page) ? this.parameters({'page': page}) : params.page; | ||
this.page = function(page) { | ||
return angular.isDefined(page) ? this.parameters({ | ||
'page': page | ||
}) : params.page; | ||
}; | ||
@@ -112,4 +125,4 @@ | ||
* @ngdoc method | ||
* @name ngTable.factory:ngTableParams#total | ||
* @methodOf ngTable.factory:ngTableParams | ||
* @name ngTable.factory:NgTableParams#total | ||
* @methodOf ngTable.factory:NgTableParams | ||
* @description If parameter total not set return current quantity else set quantity | ||
@@ -120,4 +133,6 @@ * | ||
*/ | ||
this.total = function (total) { | ||
return angular.isDefined(total) ? this.settings({'total': total}) : settings.total; | ||
this.total = function(total) { | ||
return angular.isDefined(total) ? this.settings({ | ||
'total': total | ||
}) : settings.total; | ||
}; | ||
@@ -127,4 +142,4 @@ | ||
* @ngdoc method | ||
* @name ngTable.factory:ngTableParams#count | ||
* @methodOf ngTable.factory:ngTableParams | ||
* @name ngTable.factory:NgTableParams#count | ||
* @methodOf ngTable.factory:NgTableParams | ||
* @description If parameter count not set return current count per page else set count per page | ||
@@ -135,5 +150,8 @@ * | ||
*/ | ||
this.count = function (count) { | ||
this.count = function(count) { | ||
// reset to first page because can be blank page | ||
return angular.isDefined(count) ? this.parameters({'count': count, 'page': 1}) : params.count; | ||
return angular.isDefined(count) ? this.parameters({ | ||
'count': count, | ||
'page': 1 | ||
}) : params.count; | ||
}; | ||
@@ -143,4 +161,4 @@ | ||
* @ngdoc method | ||
* @name ngTable.factory:ngTableParams#filter | ||
* @methodOf ngTable.factory:ngTableParams | ||
* @name ngTable.factory:NgTableParams#filter | ||
* @methodOf ngTable.factory:NgTableParams | ||
* @description If parameter page not set return current filter else set current filter | ||
@@ -151,4 +169,7 @@ * | ||
*/ | ||
this.filter = function (filter) { | ||
return angular.isDefined(filter) ? this.parameters({'filter': filter}) : params.filter; | ||
this.filter = function(filter) { | ||
return angular.isDefined(filter) ? this.parameters({ | ||
'filter': filter, | ||
'page': 1 | ||
}) : params.filter; | ||
}; | ||
@@ -158,4 +179,4 @@ | ||
* @ngdoc method | ||
* @name ngTable.factory:ngTableParams#sorting | ||
* @methodOf ngTable.factory:ngTableParams | ||
* @name ngTable.factory:NgTableParams#sorting | ||
* @methodOf ngTable.factory:NgTableParams | ||
* @description If 'sorting' parameter is not set, return current sorting. Otherwise set current sorting. | ||
@@ -166,10 +187,14 @@ * | ||
*/ | ||
this.sorting = function (sorting) { | ||
this.sorting = function(sorting) { | ||
if (arguments.length == 2) { | ||
var sortArray = {}; | ||
sortArray[sorting] = arguments[1]; | ||
this.parameters({'sorting': sortArray}); | ||
this.parameters({ | ||
'sorting': sortArray | ||
}); | ||
return this; | ||
} | ||
return angular.isDefined(sorting) ? this.parameters({'sorting': sorting}) : params.sorting; | ||
return angular.isDefined(sorting) ? this.parameters({ | ||
'sorting': sorting | ||
}) : params.sorting; | ||
}; | ||
@@ -179,4 +204,4 @@ | ||
* @ngdoc method | ||
* @name ngTable.factory:ngTableParams#isSortBy | ||
* @methodOf ngTable.factory:ngTableParams | ||
* @name ngTable.factory:NgTableParams#isSortBy | ||
* @methodOf ngTable.factory:NgTableParams | ||
* @description Checks sort field | ||
@@ -188,4 +213,4 @@ * | ||
*/ | ||
this.isSortBy = function (field, direction) { | ||
return angular.isDefined(params.sorting[field]) && params.sorting[field] == direction; | ||
this.isSortBy = function(field, direction) { | ||
return angular.isDefined(params.sorting[field]) && angular.equals(params.sorting[field], direction); | ||
}; | ||
@@ -195,4 +220,4 @@ | ||
* @ngdoc method | ||
* @name ngTable.factory:ngTableParams#orderBy | ||
* @methodOf ngTable.factory:ngTableParams | ||
* @name ngTable.factory:NgTableParams#orderBy | ||
* @methodOf ngTable.factory:NgTableParams | ||
* @description Return object of sorting parameters for angular filter | ||
@@ -202,3 +227,3 @@ * | ||
*/ | ||
this.orderBy = function () { | ||
this.orderBy = function() { | ||
var sorting = []; | ||
@@ -213,4 +238,4 @@ for (var column in params.sorting) { | ||
* @ngdoc method | ||
* @name ngTable.factory:ngTableParams#getData | ||
* @methodOf ngTable.factory:ngTableParams | ||
* @name ngTable.factory:NgTableParams#getData | ||
* @methodOf ngTable.factory:NgTableParams | ||
* @description Called when updated some of parameters for get new data | ||
@@ -221,3 +246,3 @@ * | ||
*/ | ||
this.getData = function ($defer, params) { | ||
this.getData = function($defer, params) { | ||
if (angular.isArray(this.data) && angular.isObject(params)) { | ||
@@ -228,2 +253,3 @@ $defer.resolve(this.data.slice((params.page() - 1) * params.count(), params.page() * params.count())); | ||
} | ||
return $defer.promise; | ||
}; | ||
@@ -233,12 +259,12 @@ | ||
* @ngdoc method | ||
* @name ngTable.factory:ngTableParams#getGroups | ||
* @methodOf ngTable.factory:ngTableParams | ||
* @name ngTable.factory:NgTableParams#getGroups | ||
* @methodOf ngTable.factory:NgTableParams | ||
* @description Return groups for table grouping | ||
*/ | ||
this.getGroups = function ($defer, column) { | ||
this.getGroups = function($defer, column) { | ||
var defer = $q.defer(); | ||
defer.promise.then(function (data) { | ||
defer.promise.then(function(data) { | ||
var groups = {}; | ||
angular.forEach(data, function (item) { | ||
angular.forEach(data, function(item) { | ||
var groupName = angular.isFunction(column) ? column(item) : item[column]; | ||
@@ -259,3 +285,3 @@ | ||
}); | ||
this.getData(defer, self); | ||
return this.getData(defer, self); | ||
}; | ||
@@ -265,4 +291,4 @@ | ||
* @ngdoc method | ||
* @name ngTable.factory:ngTableParams#generatePagesArray | ||
* @methodOf ngTable.factory:ngTableParams | ||
* @name ngTable.factory:NgTableParams#generatePagesArray | ||
* @methodOf ngTable.factory:NgTableParams | ||
* @description Generate array of pages | ||
@@ -275,3 +301,3 @@ * | ||
*/ | ||
this.generatePagesArray = function (currentPage, totalItems, pageSize) { | ||
this.generatePagesArray = function(currentPage, totalItems, pageSize) { | ||
var maxBlocks, maxPage, maxPivotPages, minPage, numPages, pages; | ||
@@ -290,3 +316,4 @@ maxBlocks = 11; | ||
number: 1, | ||
active: currentPage > 1 | ||
active: currentPage > 1, | ||
current: currentPage === 1 | ||
}); | ||
@@ -308,3 +335,4 @@ maxPivotPages = Math.round((maxBlocks - 5) / 2); | ||
number: i, | ||
active: currentPage !== i | ||
active: currentPage !== i, | ||
current: currentPage === i | ||
}); | ||
@@ -317,3 +345,4 @@ } | ||
number: numPages, | ||
active: currentPage !== numPages | ||
active: currentPage !== numPages, | ||
current: currentPage === numPages | ||
}); | ||
@@ -331,4 +360,4 @@ pages.push({ | ||
* @ngdoc method | ||
* @name ngTable.factory:ngTableParams#url | ||
* @methodOf ngTable.factory:ngTableParams | ||
* @name ngTable.factory:NgTableParams#url | ||
* @methodOf ngTable.factory:NgTableParams | ||
* @description Return groups for table grouping | ||
@@ -339,3 +368,3 @@ * | ||
*/ | ||
this.url = function (asString) { | ||
this.url = function(asString) { | ||
asString = asString || false; | ||
@@ -372,31 +401,45 @@ var pairs = (asString ? [] : {}); | ||
* @ngdoc method | ||
* @name ngTable.factory:ngTableParams#reload | ||
* @methodOf ngTable.factory:ngTableParams | ||
* @name ngTable.factory:NgTableParams#reload | ||
* @methodOf ngTable.factory:NgTableParams | ||
* @description Reload table data | ||
*/ | ||
this.reload = function () { | ||
this.reload = function() { | ||
var $defer = $q.defer(), | ||
self = this; | ||
self = this, | ||
pData = null; | ||
if (!settings.$scope) { | ||
return; | ||
} | ||
settings.$loading = true; | ||
if (settings.groupBy) { | ||
settings.getGroups($defer, settings.groupBy, this); | ||
pData = settings.getGroups($defer, settings.groupBy, this); | ||
} else { | ||
settings.getData($defer, this); | ||
pData = settings.getData($defer, this); | ||
} | ||
log('ngTable: reload data'); | ||
$defer.promise.then(function (data) { | ||
if (!pData) { | ||
// If getData resolved the $defer, and didn't promise us data, | ||
// create a promise from the $defer. We need to return a promise. | ||
pData = $defer.promise; | ||
} | ||
return pData.then(function(data) { | ||
settings.$loading = false; | ||
log('ngTable: current scope', settings.$scope); | ||
if (settings.groupBy) { | ||
self.data = settings.$scope.$groups = data; | ||
self.data = data; | ||
if (settings.$scope) settings.$scope.$groups = data; | ||
} else { | ||
self.data = settings.$scope.$data = data; | ||
self.data = data; | ||
if (settings.$scope) settings.$scope.$data = data; | ||
} | ||
settings.$scope.pages = self.generatePagesArray(self.page(), self.total(), self.count()); | ||
if (settings.$scope) settings.$scope.pages = self.generatePagesArray(self.page(), self.total(), self.count()); | ||
settings.$scope.$emit('ngTableAfterReloadData'); | ||
return data; | ||
}); | ||
}; | ||
this.reloadPages = function () { | ||
this.reloadPages = function() { | ||
var self = this; | ||
@@ -414,2 +457,4 @@ settings.$scope.pages = self.generatePagesArray(self.page(), self.total(), self.count()); | ||
}; | ||
angular.extend(params, ngTableDefaults.params); | ||
var settings = { | ||
@@ -423,5 +468,7 @@ $scope: null, // set by ngTable controller | ||
counts: [10, 25, 50, 100], | ||
sortingIndicator: 'span', | ||
getGroups: this.getGroups, | ||
getData: this.getData | ||
}; | ||
angular.extend(settings, ngTableDefaults.settings); | ||
@@ -432,3 +479,12 @@ this.settings(baseSettings); | ||
}; | ||
return ngTableParams; | ||
return NgTableParams; | ||
}]); | ||
/** | ||
* @ngdoc service | ||
* @name ngTable.factory:ngTableParams | ||
* @description Backwards compatible shim for lowercase 'n' in NgTableParams | ||
*/ | ||
app.factory('ngTableParams', ['NgTableParams', function(NgTableParams) { | ||
return NgTableParams; | ||
}]); |
@@ -16,13 +16,21 @@ /** | ||
*/ | ||
var ngTableController = ['$scope', 'ngTableParams', '$timeout', function ($scope, ngTableParams, $timeout) { | ||
app.controller('ngTableController', ['$scope', 'NgTableParams', '$timeout', '$parse', '$compile', '$attrs', '$element', | ||
'ngTableColumn', | ||
function($scope, NgTableParams, $timeout, $parse, $compile, $attrs, $element, ngTableColumn) { | ||
var isFirstTimeLoad = true; | ||
$scope.$filterRow = {}; | ||
$scope.$loading = false; | ||
if (!$scope.params) { | ||
$scope.params = new ngTableParams(); | ||
// until such times as the directive uses an isolated scope, we need to ensure that the check for | ||
// the params field only consults the "own properties" of the $scope. This is to avoid seeing the params | ||
// field on a $scope higher up in the prototype chain | ||
if (!$scope.hasOwnProperty("params")) { | ||
$scope.params = new NgTableParams(); | ||
$scope.params.isNullInstance = true; | ||
} | ||
$scope.params.settings().$scope = $scope; | ||
var delayFilter = (function () { | ||
var delayFilter = (function() { | ||
var timer = 0; | ||
return function (callback, ms) { | ||
return function(callback, ms) { | ||
$timeout.cancel(timer); | ||
@@ -33,8 +41,18 @@ timer = $timeout(callback, ms); | ||
$scope.$watch('params.$params', function (newParams, oldParams) { | ||
function resetPage() { | ||
$scope.params.$params.page = 1; | ||
} | ||
$scope.$watch('params.$params', function(newParams, oldParams) { | ||
if (newParams === oldParams) { | ||
return; | ||
} | ||
$scope.params.settings().$scope = $scope; | ||
if (!angular.equals(newParams.filter, oldParams.filter)) { | ||
delayFilter(function () { | ||
$scope.params.$params.page = 1; | ||
var maybeResetPage = isFirstTimeLoad ? angular.noop : resetPage; | ||
delayFilter(function() { | ||
maybeResetPage(); | ||
$scope.params.reload(); | ||
@@ -45,6 +63,104 @@ }, $scope.params.settings().filterDelay); | ||
} | ||
if (!$scope.params.isNullInstance) { | ||
isFirstTimeLoad = false; | ||
} | ||
}, true); | ||
$scope.sortBy = function (column, event) { | ||
var parsedSortable = $scope.parse(column.sortable); | ||
this.compileDirectiveTemplates = function () { | ||
if (!$element.hasClass('ng-table')) { | ||
$scope.templates = { | ||
header: ($attrs.templateHeader ? $attrs.templateHeader : 'ng-table/header.html'), | ||
pagination: ($attrs.templatePagination ? $attrs.templatePagination : 'ng-table/pager.html') | ||
}; | ||
$element.addClass('ng-table'); | ||
var headerTemplate = null; | ||
if ($element.find('> thead').length === 0) { | ||
headerTemplate = angular.element(document.createElement('thead')).attr('ng-include', 'templates.header'); | ||
$element.prepend(headerTemplate); | ||
} | ||
var paginationTemplate = angular.element(document.createElement('div')).attr({ | ||
'ng-table-pagination': 'params', | ||
'template-url': 'templates.pagination' | ||
}); | ||
$element.after(paginationTemplate); | ||
if (headerTemplate) { | ||
$compile(headerTemplate)($scope); | ||
} | ||
$compile(paginationTemplate)($scope); | ||
} | ||
}; | ||
this.loadFilterData = function ($columns) { | ||
angular.forEach($columns, function ($column) { | ||
var def; | ||
def = $column.filterData($scope, { | ||
$column: $column | ||
}); | ||
if (!def) { | ||
delete $column.filterData; | ||
return; | ||
} | ||
// if we're working with a deferred object, let's wait for the promise | ||
if ((angular.isObject(def) && angular.isObject(def.promise))) { | ||
delete $column.filterData; | ||
return def.promise.then(function(data) { | ||
// our deferred can eventually return arrays, functions and objects | ||
if (!angular.isArray(data) && !angular.isFunction(data) && !angular.isObject(data)) { | ||
// if none of the above was found - we just want an empty array | ||
data = []; | ||
} else if (angular.isArray(data)) { | ||
data.unshift({ | ||
title: '-', | ||
id: '' | ||
}); | ||
} | ||
$column.data = data; | ||
}); | ||
} | ||
// otherwise, we just return what the user gave us. It could be a function, array, object, whatever | ||
else { | ||
return $column.data = def; | ||
} | ||
}); | ||
}; | ||
this.buildColumns = function (columns) { | ||
return columns.map(function(col){ | ||
return ngTableColumn.buildColumn(col, $scope) | ||
}) | ||
}; | ||
this.setupBindingsToInternalScope = function(tableParamsExpr){ | ||
// note: this we're setting up watches to simulate angular's isolated scope bindings | ||
// note: is REALLY important to watch for a change to the ngTableParams *reference* rather than | ||
// $watch for value equivalence. This is because ngTableParams references the current page of data as | ||
// a field and it's important not to watch this | ||
var tableParamsGetter = $parse(tableParamsExpr); | ||
$scope.$watch(tableParamsGetter, (function (params) { | ||
if (angular.isUndefined(params)) { | ||
return; | ||
} | ||
$scope.paramsModel = tableParamsGetter; | ||
$scope.params = params; | ||
}), false); | ||
if ($attrs.showFilter) { | ||
$scope.$parent.$watch($attrs.showFilter, function(value) { | ||
$scope.show_filter = value; | ||
}); | ||
} | ||
if ($attrs.disableFilter) { | ||
$scope.$parent.$watch($attrs.disableFilter, function(value) { | ||
$scope.$filterRow.disabled = value; | ||
}); | ||
} | ||
}; | ||
$scope.sortBy = function($column, event) { | ||
var parsedSortable = $column.sortable && $column.sortable(); | ||
if (!parsedSortable) { | ||
@@ -62,2 +178,72 @@ return; | ||
}; | ||
}]; | ||
}]); | ||
/** | ||
* @ngdoc service | ||
* @name ngTable.factory:ngTableColumn | ||
* | ||
* @description | ||
* Service to construct a $column definition used by {@link ngTable.directive:ngTable ngTable} directive | ||
*/ | ||
app.factory('ngTableColumn', [function () { | ||
var defaults = { | ||
'class': function(){ return ''; }, | ||
filter: function(){ return false; }, | ||
filterData: angular.noop, | ||
headerTemplateURL: function(){ return false; }, | ||
headerTitle: function(){ return ''; }, | ||
sortable: function(){ return false; }, | ||
show: function(){ return true; }, | ||
title: function(){ return ''; }, | ||
titleAlt: function(){ return ''; } | ||
}; | ||
/** | ||
* @ngdoc method | ||
* @name ngTable.factory:ngTableColumn#buildColumn | ||
* @methodOf ngTable.factory:ngTableColumn | ||
* @description Creates a $column for use within a header template | ||
* | ||
* @param {Object} column an existing $column or simple column data object | ||
* @param {Scope} defaultScope the $scope to supply to the $column getter methods when not supplied by caller | ||
* @returns {Object} a $column object | ||
*/ | ||
function buildColumn(column, defaultScope){ | ||
// note: we're not modifying the original column object. This helps to avoid unintended side affects | ||
var extendedCol = Object.create(column); | ||
for (var prop in defaults) { | ||
if (extendedCol[prop] === undefined) { | ||
extendedCol[prop] = defaults[prop]; | ||
} | ||
if(!angular.isFunction(extendedCol[prop])){ | ||
// wrap raw field values with "getter" functions | ||
// - this is to ensure consistency with how ngTable.compile builds columns | ||
// - note that the original column object is being "proxied"; this is important | ||
// as it ensure that any changes to the original object will be returned by the "getter" | ||
(function(prop1){ | ||
extendedCol[prop1] = function(){ | ||
return column[prop1]; | ||
}; | ||
})(prop); | ||
} | ||
(function(prop1){ | ||
// satisfy the arguments expected by the function returned by parsedAttribute in the ngTable directive | ||
var getterFn = extendedCol[prop1]; | ||
extendedCol[prop1] = function(){ | ||
if (arguments.length === 0){ | ||
return getterFn.call(column, defaultScope); | ||
} else { | ||
return getterFn.apply(column, arguments); | ||
} | ||
}; | ||
})(prop); | ||
} | ||
return extendedCol; | ||
} | ||
return { | ||
buildColumn: buildColumn | ||
}; | ||
}]); |
@@ -17,4 +17,4 @@ /** | ||
*/ | ||
app.directive('ngTable', ['$compile', '$q', '$parse', | ||
function ($compile, $q, $parse) { | ||
app.directive('ngTable', ['$q', '$parse', | ||
function($q, $parse) { | ||
'use strict'; | ||
@@ -26,11 +26,10 @@ | ||
scope: true, | ||
controller: ngTableController, | ||
compile: function (element) { | ||
var columns = [], i = 0, row = null; | ||
controller: 'ngTableController', | ||
compile: function(element) { | ||
var columns = [], | ||
i = 0, | ||
row = null; | ||
// custom header | ||
var thead = element.find('thead'); | ||
// IE 8 fix :not(.ng-table-group) selector | ||
angular.forEach(angular.element(element.find('tr')), function (tr) { | ||
angular.forEach(angular.element(element.find('tr')), function(tr) { | ||
tr = angular.element(tr); | ||
@@ -44,3 +43,3 @@ if (!tr.hasClass('ng-table-group') && !row) { | ||
} | ||
angular.forEach(row.find('td'), function (item) { | ||
angular.forEach(row.find('td'), function(item) { | ||
var el = angular.element(item); | ||
@@ -50,109 +49,122 @@ if (el.attr('ignore-cell') && 'true' === el.attr('ignore-cell')) { | ||
} | ||
var parsedAttribute = function (attr, defaultValue) { | ||
return function (scope) { | ||
return $parse(el.attr('x-data-' + attr) || el.attr('data-' + attr) || el.attr(attr))(scope, { | ||
var getAttrValue = function(attr){ | ||
return el.attr('x-data-' + attr) || el.attr('data-' + attr) || el.attr(attr); | ||
}; | ||
var parsedAttribute = function(attr) { | ||
var expr = getAttrValue(attr); | ||
if (!expr){ | ||
return undefined; | ||
} | ||
return function(scope, locals) { | ||
return $parse(expr)(scope, angular.extend(locals || {}, { | ||
$columns: columns | ||
}) || defaultValue; | ||
})); | ||
}; | ||
}; | ||
var parsedTitle = parsedAttribute('title', ' '), | ||
headerTemplateURL = parsedAttribute('header', false), | ||
filter = parsedAttribute('filter', false)(), | ||
filterTemplateURL = false, | ||
filterName = false; | ||
if (filter && filter.$$name) { | ||
filterName = filter.$$name; | ||
delete filter.$$name; | ||
var titleExpr = getAttrValue('title-alt') || getAttrValue('title'); | ||
if (titleExpr){ | ||
el.attr('data-title-text', '{{' + titleExpr + '}}'); // this used in responsive table | ||
} | ||
if (filter && filter.templateURL) { | ||
filterTemplateURL = filter.templateURL; | ||
delete filter.templateURL; | ||
} | ||
el.attr('data-title-text', parsedTitle()); // this used in responsive table | ||
// NOTE TO MAINTAINERS: if you add extra fields to a $column be sure to extend ngTableColumn with | ||
// a corresponding "safe" default | ||
columns.push({ | ||
id: i++, | ||
title: parsedTitle, | ||
sortable: parsedAttribute('sortable', false), | ||
'class': el.attr('x-data-header-class') || el.attr('data-header-class') || el.attr('header-class'), | ||
filter: filter, | ||
filterTemplateURL: filterTemplateURL, | ||
filterName: filterName, | ||
headerTemplateURL: headerTemplateURL, | ||
filterData: (el.attr("filter-data") ? el.attr("filter-data") : null), | ||
title: parsedAttribute('title'), | ||
titleAlt: parsedAttribute('title-alt'), | ||
headerTitle: parsedAttribute('header-title'), | ||
sortable: parsedAttribute('sortable'), | ||
'class': parsedAttribute('header-class'), | ||
filter: parsedAttribute('filter'), | ||
headerTemplateURL: parsedAttribute('header'), | ||
filterData: parsedAttribute('filter-data'), | ||
show: (el.attr("ng-show") ? function (scope) { | ||
return $parse(el.attr("ng-show"))(scope); | ||
} : function () { | ||
return true; | ||
}) | ||
} : undefined) | ||
}); | ||
}); | ||
return function (scope, element, attrs) { | ||
scope.$loading = false; | ||
scope.$columns = columns; | ||
return function(scope, element, attrs, controller) { | ||
scope.$columns = columns = controller.buildColumns(columns); | ||
scope.$watch(attrs.ngTable, (function (params) { | ||
if (angular.isUndefined(params)) { | ||
return; | ||
} | ||
scope.paramsModel = $parse(attrs.ngTable); | ||
scope.params = params; | ||
}), true); | ||
scope.parse = function (text) { | ||
return angular.isDefined(text) ? text(scope) : ''; | ||
}; | ||
if (attrs.showFilter) { | ||
scope.$parent.$watch(attrs.showFilter, function (value) { | ||
scope.show_filter = value; | ||
}); | ||
} | ||
angular.forEach(columns, function (column) { | ||
var def; | ||
if (!column.filterData) { | ||
return; | ||
} | ||
def = $parse(column.filterData)(scope, { | ||
$column: column | ||
}); | ||
if (!(angular.isObject(def) && angular.isObject(def.promise))) { | ||
throw new Error('Function ' + column.filterData + ' must be instance of $q.defer()'); | ||
} | ||
delete column.filterData; | ||
return def.promise.then(function (data) { | ||
if (!angular.isArray(data)) { | ||
data = []; | ||
} | ||
data.unshift({ | ||
title: '-', | ||
id: '' | ||
}); | ||
column.data = data; | ||
}); | ||
}); | ||
if (!element.hasClass('ng-table')) { | ||
scope.templates = { | ||
header: (attrs.templateHeader ? attrs.templateHeader : 'ng-table/header.html'), | ||
pagination: (attrs.templatePagination ? attrs.templatePagination : 'ng-table/pager.html') | ||
}; | ||
var headerTemplate = thead.length > 0 ? thead : angular.element(document.createElement('thead')).attr('ng-include', 'templates.header'); | ||
var paginationTemplate = angular.element(document.createElement('div')).attr({ | ||
'ng-table-pagination': 'params', | ||
'template-url': 'templates.pagination' | ||
}); | ||
controller.setupBindingsToInternalScope(attrs.ngTable); | ||
controller.loadFilterData(columns); | ||
controller.compileDirectiveTemplates(); | ||
}; | ||
} | ||
} | ||
} | ||
]); | ||
element.find('thead').remove(); | ||
/** | ||
* @ngdoc directive | ||
* @name ngTable.directive:ngTableDynamic | ||
* @restrict A | ||
* | ||
* @description | ||
* A dynamic version of the {@link ngTable.directive:ngTable ngTable} directive that accepts a dynamic list of columns | ||
* definitions to render | ||
*/ | ||
app.directive('ngTableDynamic', ['$parse', function ($parse){ | ||
element.addClass('ng-table') | ||
.prepend(headerTemplate) | ||
.after(paginationTemplate); | ||
function parseDirectiveExpression(attr) { | ||
if (!attr || attr.indexOf(" with ") > -1) { | ||
var parts = attr.split(/\s+with\s+/); | ||
return { | ||
tableParams: parts[0], | ||
columns: parts[1] | ||
}; | ||
} else { | ||
throw new Error('Parse error (expected example: ng-table-dynamic=\'tableParams with cols\')'); | ||
} | ||
} | ||
$compile(headerTemplate)(scope); | ||
$compile(paginationTemplate)(scope); | ||
} | ||
return { | ||
restrict: 'A', | ||
priority: 1001, | ||
scope: true, | ||
controller: 'ngTableController', | ||
compile: function(tElement) { | ||
var row; | ||
// IE 8 fix :not(.ng-table-group) selector | ||
angular.forEach(angular.element(tElement.find('tr')), function(tr) { | ||
tr = angular.element(tr); | ||
if (!tr.hasClass('ng-table-group') && !row) { | ||
row = tr; | ||
} | ||
}); | ||
if (!row) { | ||
return; | ||
} | ||
angular.forEach(row.find('td'), function(item) { | ||
var el = angular.element(item); | ||
var getAttrValue = function(attr){ | ||
return el.attr('x-data-' + attr) || el.attr('data-' + attr) || el.attr(attr); | ||
}; | ||
} | ||
// this used in responsive table | ||
var titleExpr = getAttrValue('title'); | ||
if (!titleExpr){ | ||
el.attr('data-title-text', '{{$columns[$index].titleAlt(this) || $columns[$index].title(this)}}'); | ||
} | ||
var showExpr = el.attr('ng-show'); | ||
if (!showExpr){ | ||
el.attr('ng-show', '$columns[$index].show(this)'); | ||
} | ||
}); | ||
return function(scope, element, attrs, controller) { | ||
var expr = parseDirectiveExpression(attrs.ngTableDynamic); | ||
var columns = $parse(expr.columns)(scope) || []; | ||
scope.$columns = controller.buildColumns(columns); | ||
controller.setupBindingsToInternalScope(expr.tableParams); | ||
controller.loadFilterData(scope.$columns); | ||
controller.compileDirectiveTemplates(); | ||
}; | ||
} | ||
} | ||
]); | ||
}; | ||
}]); |
@@ -15,3 +15,3 @@ /** | ||
app.directive('ngTablePagination', ['$compile', | ||
function ($compile) { | ||
function($compile) { | ||
'use strict'; | ||
@@ -26,5 +26,5 @@ | ||
replace: false, | ||
link: function (scope, element, attrs) { | ||
link: function(scope, element, attrs) { | ||
scope.params.settings().$scope.$on('ngTableAfterReloadData', function () { | ||
scope.params.settings().$scope.$on('ngTableAfterReloadData', function() { | ||
scope.pages = scope.params.generatePagesArray(scope.params.page(), scope.params.total(), scope.params.count()); | ||
@@ -47,2 +47,2 @@ }, true); | ||
} | ||
]); | ||
]); |
@@ -1,2 +0,2 @@ | ||
describe('ngTableParams', function () { | ||
describe('NgTableParams', function () { | ||
var scope, ctrl, params, data = [ | ||
@@ -23,5 +23,5 @@ {name: "Moroni", age: 50, role: 'Administrator'}, | ||
/*beforeEach(inject(function ($controller, $rootScope, ngTableParams) { | ||
/*beforeEach(inject(function ($controller, $rootScope, NgTableParams) { | ||
scope = $rootScope.$new(); | ||
params = scope.params = new ngTableParams(); | ||
params = scope.params = new NgTableParams(); | ||
ctrl = $controller(ngTableController, { | ||
@@ -32,6 +32,6 @@ $scope: scope | ||
it('ngTableController should have parameters', inject(function (ngTableParams) { | ||
var params = new ngTableParams(); | ||
expect(ngTableParams).toBeDefined(); | ||
it('ngTableController should have parameters', inject(function (NgTableParams) { | ||
var params = new NgTableParams(); | ||
expect(NgTableParams).toBeDefined(); | ||
}));*/ | ||
}); | ||
}); |
@@ -1,2 +0,2 @@ | ||
describe('ngTableParams', function () { | ||
describe('NgTableParams', function () { | ||
var scope, ctrl, data = [ | ||
@@ -27,14 +27,14 @@ {name: "Moroni", age: 50, role: 'Administrator'}, | ||
it('ngTableParams should be defined', inject(function (ngTableParams) { | ||
var params = new ngTableParams(); | ||
expect(ngTableParams).toBeDefined(); | ||
it('NgTableParams should be defined', inject(function (NgTableParams) { | ||
var params = new NgTableParams(); | ||
expect(NgTableParams).toBeDefined(); | ||
})); | ||
it('ngTableParams test generatePagesArray', inject(function (ngTableParams) { | ||
var params = new ngTableParams(); | ||
it('NgTableParams test generatePagesArray', inject(function (NgTableParams) { | ||
var params = new NgTableParams(); | ||
expect(params.generatePagesArray(1, 30, 10)).toEqual([ | ||
{ type: 'prev', number: 1, active: false }, | ||
{ type: 'first', number: 1, active: false }, | ||
{ type: 'page', number: 2, active: true }, | ||
{ type: 'last', number: 3, active: true }, | ||
{ type: 'first', number: 1, active: false, current: true }, | ||
{ type: 'page', number: 2, active: true, current: false }, | ||
{ type: 'last', number: 3, active: true, current: false }, | ||
{ type: 'next', number: 2, active: true } | ||
@@ -44,5 +44,5 @@ ]); | ||
{ type: 'prev', number: 1, active: true }, | ||
{ type: 'first', number: 1, active: true }, | ||
{ type: 'page', number: 2, active: false }, | ||
{ type: 'last', number: 3, active: true }, | ||
{ type: 'first', number: 1, active: true, current: false }, | ||
{ type: 'page', number: 2, active: false, current: true }, | ||
{ type: 'last', number: 3, active: true, current: false }, | ||
{ type: 'next', number: 3, active: true } | ||
@@ -52,11 +52,11 @@ ]); | ||
{ type: 'prev', number: 1, active: true }, | ||
{ type: 'first', number: 1, active: true }, | ||
{ type: 'page', number: 2, active: false }, | ||
{ type: 'page', number: 3, active: true }, | ||
{ type: 'page', number: 4, active: true }, | ||
{ type: 'page', number: 5, active: true }, | ||
{ type: 'page', number: 6, active: true }, | ||
{ type: 'page', number: 7, active: true }, | ||
{ type: 'first', number: 1, active: true, current: false }, | ||
{ type: 'page', number: 2, active: false, current: true }, | ||
{ type: 'page', number: 3, active: true, current: false }, | ||
{ type: 'page', number: 4, active: true, current: false }, | ||
{ type: 'page', number: 5, active: true, current: false }, | ||
{ type: 'page', number: 6, active: true, current: false }, | ||
{ type: 'page', number: 7, active: true, current: false }, | ||
{ type: 'more', active: false }, | ||
{ type: 'last', number: 10, active: true }, | ||
{ type: 'last', number: 10, active: true, current: false }, | ||
{ type: 'next', number: 3, active: true } | ||
@@ -66,4 +66,4 @@ ]); | ||
it('ngTableParams `page` parameter', inject(function (ngTableParams) { | ||
var params = new ngTableParams(); | ||
it('NgTableParams `page` parameter', inject(function (NgTableParams) { | ||
var params = new NgTableParams(); | ||
@@ -74,3 +74,3 @@ expect(params.page()).toBe(1); | ||
params = new ngTableParams({ | ||
params = new NgTableParams({ | ||
page: 3 | ||
@@ -94,4 +94,4 @@ }); | ||
it('ngTableParams parse url parameters', inject(function (ngTableParams) { | ||
var params = new ngTableParams({ | ||
it('NgTableParams parse url parameters', inject(function (NgTableParams) { | ||
var params = new NgTableParams({ | ||
'sorting[name]': 'asc', | ||
@@ -110,4 +110,4 @@ 'sorting[age]': 'desc', | ||
it('ngTableParams return url parameters', inject(function (ngTableParams) { | ||
var params = new ngTableParams({ | ||
it('NgTableParams return url parameters', inject(function (NgTableParams) { | ||
var params = new NgTableParams({ | ||
'sorting[name]': 'asc', | ||
@@ -134,4 +134,4 @@ 'sorting[age]': 'desc', | ||
it('ngTableParams test orderBy', inject(function (ngTableParams) { | ||
var params = new ngTableParams({ | ||
it('NgTableParams test orderBy', inject(function (NgTableParams) { | ||
var params = new NgTableParams({ | ||
'sorting[name]': 'asc' | ||
@@ -147,4 +147,4 @@ }); | ||
it('ngTableParams test settings', inject(function (ngTableParams) { | ||
var params = new ngTableParams(); | ||
it('NgTableParams test settings', inject(function (NgTableParams) { | ||
var params = new NgTableParams(); | ||
@@ -158,2 +158,3 @@ expect(params.settings()).toEqual({ | ||
counts: [10, 25, 50, 100], | ||
sortingIndicator : 'span', | ||
getData: params.getData, | ||
@@ -164,3 +165,3 @@ getGroups: params.getGroups, | ||
params = new ngTableParams({}, { total: 100 }); | ||
params = new NgTableParams({}, { total: 100 }); | ||
@@ -174,2 +175,3 @@ expect(params.settings()).toEqual({ | ||
counts: [10, 25, 50, 100], | ||
sortingIndicator : 'span', | ||
getData: params.getData, | ||
@@ -181,4 +183,4 @@ getGroups: params.getGroups, | ||
it('ngTableParams test getData', inject(function ($q, ngTableParams) { | ||
var params = new ngTableParams(); | ||
it('NgTableParams test getData', inject(function ($q, NgTableParams) { | ||
var params = new NgTableParams(); | ||
$defer = $q.defer(); | ||
@@ -191,4 +193,4 @@ $defer.promise.then(function(data) { | ||
it('ngTableParams test grouping', inject(function ($q, ngTableParams) { | ||
var params = new ngTableParams(); | ||
it('NgTableParams test grouping', inject(function ($q, NgTableParams) { | ||
var params = new NgTableParams(); | ||
params.getData = function ($defer) { | ||
@@ -287,2 +289,19 @@ $defer.resolve(data); | ||
})); | ||
it('ngTableParams test defaults', inject(function ($q, ngTableParams, ngTableDefaults) { | ||
ngTableDefaults.params = { | ||
count: 2 | ||
}; | ||
ngTableDefaults.settings = { | ||
counts: [] | ||
}; | ||
var params = new ngTableParams(); | ||
expect(params.count()).toEqual(2); | ||
expect(params.page()).toEqual(1); | ||
var settings = params.settings() | ||
expect(settings.counts.length).toEqual(0); | ||
expect(settings.filterDelay).toEqual(750); | ||
})); | ||
}); |
@@ -1,20 +0,20 @@ | ||
describe('ng-table', function () { | ||
var elm, scope, data = [ | ||
{id: 1, name: "Moroni", age: 50, money: -10}, | ||
{id: 2, name: "Tiancum", age: 43, money: 120}, | ||
{id: 3, name: "Jacob", age: 27, money: 5.5}, | ||
{id: 4, name: "Nephi", age: 29, money: -54}, | ||
{id: 5, name: "Enos", age: 34, money: 110}, | ||
{id: 6, name: "Tiancum", age: 43, money: 1000}, | ||
{id: 7, name: "Jacob", age: 27, money: -201}, | ||
{id: 8, name: "Nephi", age: 29, money: 100}, | ||
{id: 9, name: "Enos", age: 34, money: -52.5}, | ||
{id: 10, name: "Tiancum", age: 43, money: 52.1}, | ||
{id: 11, name: "Jacob", age: 27, money: 110}, | ||
{id: 12, name: "Nephi", age: 29, money: -55}, | ||
{id: 13, name: "Enos", age: 34, money: 551}, | ||
{id: 14, name: "Tiancum", age: 43, money: -1410}, | ||
{id: 15, name: "Jacob", age: 27, money: 410}, | ||
{id: 16, name: "Nephi", age: 29, money: 100}, | ||
{id: 17, name: "Enos", age: 34, money: -100} | ||
describe('ng-table', function() { | ||
var data = [ | ||
{ id: 1, name: "Moroni", age: 50, money: -10 }, | ||
{ id: 2, name: "Tiancum", age: 43, money: 120 }, | ||
{ id: 3, name: "Jacob", age: 27, money: 5.5 }, | ||
{ id: 4, name: "Nephi", age: 29, money: -54 }, | ||
{ id: 5, name: "Enos", age: 34, money: 110 }, | ||
{ id: 6, name: "Tiancum", age: 43, money: 1000 }, | ||
{ id: 7, name: "Jacob", age: 27, money: -201 }, | ||
{ id: 8, name: "Nephi", age: 29, money: 100 }, | ||
{ id: 9, name: "Enos", age: 34, money: -52.5 }, | ||
{ id: 10, name: "Tiancum", age: 43, money: 52.1 }, | ||
{ id: 11, name: "Jacob", age: 27, money: 110 }, | ||
{ id: 12, name: "Nephi", age: 29, money: -55 }, | ||
{ id: 13, name: "Enos", age: 34, money: 551 }, | ||
{ id: 14, name: "Tiancum", age: 43, money: -1410 }, | ||
{ id: 15, name: "Jacob", age: 27, money: 410 }, | ||
{ id: 16, name: "Nephi", age: 29, money: 100 }, | ||
{ id: 17, name: "Enos", age: 34, money: -100 } | ||
]; | ||
@@ -24,91 +24,458 @@ | ||
beforeEach(inject(function ($rootScope, $compile, $q) { | ||
elm = angular.element( | ||
'<div>' + | ||
'<script type="text/ng-template" id="ng-table/filters/money.html"></script>' + | ||
'<table ng-table="tableParams" show-filter="true">' + | ||
'<tr ng-repeat="user in $data">' + | ||
'<td data-title="\'Name of person\'" filter="{ \'name\': \'text\' }" sortable="name">' + | ||
'{{user.name}}' + | ||
'</td>' + | ||
'<td x-data-title="\'Age\'" sortable="age">' + | ||
'{{user.age}}' + | ||
'</td>' + | ||
'<td title="\'Money\'" filter="{ \'action\': \'money\' }" filter-data="money($column)">' + | ||
'{{user.money}}' + | ||
'</td>' + | ||
'</tr>' + | ||
'</table>' + | ||
'</div>'); | ||
var scope; | ||
beforeEach(inject(function($rootScope) { | ||
scope = $rootScope.$new(true); | ||
})); | ||
scope.money = function() { | ||
var def = $q.defer(); | ||
describe('basics', function(){ | ||
var elm; | ||
beforeEach(inject(function($compile, $q) { | ||
elm = angular.element( | ||
'<div>' + | ||
'<table ng-table="tableParams" show-filter="true">' + | ||
'<tr ng-repeat="user in $data">' + | ||
'<td data-header-title="\'Sort by Name\'" data-title="nameTitle()" filter="{ \'name\': \'text\' }" sortable="\'name\'" data-header-class="getCustomClass($column)">' + | ||
'{{user.name}}' + | ||
'</td>' + | ||
'<td x-data-header-title="\'Sort by Age\'" x-data-title="ageTitle()" sortable="\'age\'" x-data-header-class="getCustomClass($column)">' + | ||
'{{user.age}}' + | ||
'</td>' + | ||
'<td header-title="\'Sort by Money\'" title="moneyTitle()" filter="{ \'action\': \'select\' }" filter-data="money($column)" header-class="getCustomClass($column)">' + | ||
'{{user.money}}' + | ||
'</td>' + | ||
'</tr>' + | ||
'</table>' + | ||
'</div>'); | ||
def.resolve([{ | ||
'id': 10, | ||
'title': '10' | ||
}]); | ||
return def; | ||
}; | ||
scope.nameTitle = function(){ | ||
return 'Name of person'; | ||
}; | ||
scope.ageTitle = function(){ | ||
return 'Age'; | ||
}; | ||
scope.moneyTitle = function(){ | ||
return 'Money'; | ||
}; | ||
$compile(elm)(scope); | ||
scope.$digest(); | ||
})); | ||
scope.getCustomClass = function($column){ | ||
if ($column.title().indexOf('Money') !== -1){ | ||
return 'moneyHeaderClass'; | ||
} else{ | ||
return 'customClass'; | ||
} | ||
}; | ||
it('should create table header', inject(function ($compile, $rootScope) { | ||
var thead = elm.find('thead'); | ||
expect(thead.length).toBe(1); | ||
scope.money = function(/*$column*/) { | ||
var rows = thead.find('tr'); | ||
expect(rows.length).toBe(2); | ||
var def = $q.defer(); | ||
var titles = angular.element(rows[0]).find('th'); | ||
def.resolve([{ | ||
'id': 10, | ||
'title': '10' | ||
}]); | ||
return def; | ||
}; | ||
expect(titles.length).toBe(3); | ||
expect(angular.element(titles[0]).text().trim()).toBe('Name of person'); | ||
expect(angular.element(titles[1]).text().trim()).toBe('Age'); | ||
expect(angular.element(titles[2]).text().trim()).toBe('Money'); | ||
$compile(elm)(scope); | ||
scope.$digest(); | ||
})); | ||
var filters = angular.element(rows[1]).find('th'); | ||
expect(filters.length).toBe(3); | ||
})); | ||
it('should create table header', function() { | ||
var thead = elm.find('thead'); | ||
expect(thead.length).toBe(1); | ||
it('should show scope data', inject(function ($compile, $rootScope, ngTableParams) { | ||
debugger; | ||
var tbody = elm.find('tbody'); | ||
expect(tbody.length).toBe(1); | ||
var rows = thead.find('tr'); | ||
expect(rows.length).toBe(2); | ||
var rows = tbody.find('tr'); | ||
expect(rows.length).toBe(0); | ||
var titles = angular.element(rows[0]).find('th'); | ||
var params = new ngTableParams({ | ||
page: 1, // show first page | ||
count: 10 // count per page | ||
}, { | ||
total: data.length, // length of data | ||
getData: function($defer, params) { | ||
$defer.resolve(data.slice((params.page() - 1) * params.count(), params.page() * params.count())); | ||
} | ||
expect(titles.length).toBe(3); | ||
expect(angular.element(titles[0]).text().trim()).toBe('Name of person'); | ||
expect(angular.element(titles[1]).text().trim()).toBe('Age'); | ||
expect(angular.element(titles[2]).text().trim()).toBe('Money'); | ||
expect(angular.element(rows[1]).hasClass('ng-table-filters')).toBeTruthy(); | ||
var filters = angular.element(rows[1]).find('th'); | ||
expect(filters.length).toBe(3); | ||
expect(angular.element(filters[0]).hasClass('filter')).toBeTruthy(); | ||
expect(angular.element(filters[1]).hasClass('filter')).toBeTruthy(); | ||
expect(angular.element(filters[2]).hasClass('filter')).toBeTruthy(); | ||
}); | ||
scope.tableParams = params; | ||
scope.$digest(); | ||
rows = tbody.find('tr'); | ||
expect(rows.length).toBe(10); | ||
it('should create table header classes', inject(function($compile, $rootScope) { | ||
scope.tableParams.page(2); | ||
scope.$digest(); | ||
rows = tbody.find('tr'); | ||
expect(rows.length).toBe(7); | ||
var thead = elm.find('thead'); | ||
var rows = thead.find('tr'); | ||
var titles = angular.element(rows[0]).find('th'); | ||
params.total(20); | ||
scope.$digest(); | ||
expect(angular.element(titles[0]).hasClass('header')).toBeTruthy(); | ||
expect(angular.element(titles[1]).hasClass('header')).toBeTruthy(); | ||
expect(angular.element(titles[2]).hasClass('header')).toBeTruthy(); | ||
rows = tbody.find('tr'); | ||
expect(rows.length).toBe(7); | ||
})); | ||
expect(angular.element(titles[0]).hasClass('sortable')).toBeTruthy(); | ||
expect(angular.element(titles[1]).hasClass('sortable')).toBeTruthy(); | ||
expect(angular.element(titles[2]).hasClass('sortable')).toBeFalsy(); | ||
}); | ||
expect(angular.element(titles[0]).hasClass('customClass')).toBeTruthy(); | ||
expect(angular.element(titles[1]).hasClass('customClass')).toBeTruthy(); | ||
expect(angular.element(titles[2]).hasClass('moneyHeaderClass')).toBeTruthy(); | ||
})); | ||
it('should create table header titles', function() { | ||
var thead = elm.find('thead'); | ||
var rows = thead.find('tr'); | ||
var titles = angular.element(rows[0]).find('th'); | ||
expect(angular.element(titles[0]).attr('title').trim()).toBe('Sort by Name'); | ||
expect(angular.element(titles[1]).attr('title').trim()).toBe('Sort by Age'); | ||
expect(angular.element(titles[2]).attr('title').trim()).toBe('Sort by Money'); | ||
}); | ||
it('should show scope data', inject(function(NgTableParams) { | ||
var tbody = elm.find('tbody'); | ||
expect(tbody.length).toBe(1); | ||
var rows = tbody.find('tr'); | ||
expect(rows.length).toBe(0); | ||
var params = new NgTableParams({ | ||
page: 1, // show first page | ||
count: 10 // count per page | ||
}, { | ||
total: data.length, // length of data | ||
getData: function($defer, params) { | ||
$defer.resolve(data.slice((params.page() - 1) * params.count(), params.page() * params.count())); | ||
} | ||
}); | ||
scope.tableParams = params; | ||
scope.$digest(); | ||
rows = tbody.find('tr'); | ||
expect(rows.length).toBe(10); | ||
scope.tableParams.page(2); | ||
scope.$digest(); | ||
rows = tbody.find('tr'); | ||
expect(rows.length).toBe(7); | ||
params.total(20); | ||
scope.$digest(); | ||
rows = tbody.find('tr'); | ||
expect(rows.length).toBe(7); | ||
})); | ||
it('should show data-title-text', inject(function(NgTableParams) { | ||
var tbody = elm.find('tbody'); | ||
var params = new NgTableParams({ | ||
page: 1, // show first page | ||
count: 10 // count per page | ||
}, { | ||
total: data.length, // length of data | ||
getData: function($defer, params) { | ||
$defer.resolve(data); | ||
} | ||
}); | ||
scope.tableParams = params; | ||
scope.$digest(); | ||
var filterRow = angular.element(elm.find('thead').find('tr')[1]); | ||
var filterCells = filterRow.find('th'); | ||
expect(angular.element(filterCells[0]).attr('data-title-text').trim()).toBe('Name of person'); | ||
expect(angular.element(filterCells[1]).attr('data-title-text').trim()).toBe('Age'); | ||
expect(angular.element(filterCells[2]).attr('data-title-text').trim()).toBe('Money'); | ||
var dataRows = elm.find('tbody').find('tr'); | ||
var dataCells = angular.element(dataRows[0]).find('td'); | ||
expect(angular.element(dataCells[0]).attr('data-title-text').trim()).toBe('Name of person'); | ||
expect(angular.element(dataCells[1]).attr('data-title-text').trim()).toBe('Age'); | ||
expect(angular.element(dataCells[2]).attr('data-title-text').trim()).toBe('Money'); | ||
})); | ||
}); | ||
describe('title-alt', function() { | ||
var elm; | ||
beforeEach(inject(function($compile, NgTableParams) { | ||
elm = angular.element( | ||
'<table ng-table="tableParams">' + | ||
'<tr ng-repeat="user in $data">' + | ||
'<td title="\'Name of person\'" title-alt="\'Name\'">{{user.name}}</td>' + | ||
'<td title="\'Age of person\'" data-title-alt="\'Age\'">{{user.age}}</td>' + | ||
'<td title="\'Money earned\'" x-data-title-alt="\'£\'">{{user.money}}</td>' + | ||
'</tr>' + | ||
'</table>'); | ||
$compile(elm)(scope); | ||
scope.$digest(); | ||
var params = new NgTableParams({ | ||
page: 1, // show first page | ||
count: 10 // count per page | ||
}, { | ||
total: data.length, // length of data | ||
getData: function($defer, params) { | ||
$defer.resolve(data); | ||
} | ||
}); | ||
scope.tableParams = params; | ||
scope.$digest(); | ||
})); | ||
it('should show as data-title-text', inject(function($compile) { | ||
var filterRow = angular.element(elm.find('thead').find('tr')[1]); | ||
var filterCells = filterRow.find('th'); | ||
expect(angular.element(filterCells[0]).attr('data-title-text').trim()).toBe('Name'); | ||
expect(angular.element(filterCells[1]).attr('data-title-text').trim()).toBe('Age'); | ||
expect(angular.element(filterCells[2]).attr('data-title-text').trim()).toBe('£'); | ||
var dataRows = elm.find('tbody').find('tr'); | ||
var dataCells = angular.element(dataRows[0]).find('td'); | ||
expect(angular.element(dataCells[0]).attr('data-title-text').trim()).toBe('Name'); | ||
expect(angular.element(dataCells[1]).attr('data-title-text').trim()).toBe('Age'); | ||
expect(angular.element(dataCells[2]).attr('data-title-text').trim()).toBe('£'); | ||
})); | ||
}); | ||
describe('sorting', function() { | ||
it('should provide $column definition', inject(function($compile) { | ||
var columnDef; | ||
var elm = angular.element( | ||
'<table ng-table="tableParams">' + | ||
'<tr ng-repeat="user in $data">' + | ||
'<td title="\'Age\'" sortable="captureColumn($column)">{{user.age}}</td>' + | ||
'</tr>' + | ||
'</table>'); | ||
scope.captureColumn = function($column){ | ||
columnDef = $column; | ||
return 'age' | ||
}; | ||
$compile(elm)(scope); | ||
scope.$digest(); | ||
expect(columnDef).toBeDefined(); | ||
})); | ||
}); | ||
describe('filters', function(){ | ||
var $capturedColumn; | ||
beforeEach(inject(function() { | ||
// stash a reference to $column definition so that its available in asserts | ||
scope.captureColumn = function ($column) { | ||
$capturedColumn = $column; | ||
}; | ||
})); | ||
describe('filter specified as alias', function(){ | ||
var elm; | ||
beforeEach(inject(function($compile, NgTableParams) { | ||
elm = angular.element( | ||
'<div>' + | ||
'<table ng-table="tableParams" show-filter="true">' + | ||
'<tr ng-repeat="user in $data">' + | ||
'<td header-class="captureColumn($column)" title="\'Name\'" ' + | ||
'filter="usernameFilter">{{user.name}}</td>' + | ||
'</tr>' + | ||
'</table>' + | ||
'</div>'); | ||
$compile(elm)(scope); | ||
scope.$digest(); | ||
// 'text' is a shortcut alias for the template ng-table/filters/text | ||
scope.usernameFilter = {username: 'text'}; | ||
scope.tableParams = new NgTableParams({}, {}); | ||
scope.$digest(); | ||
})); | ||
it('should render named filter template', function() { | ||
var inputs = elm.find('thead').find('tr').eq(1).find('th').find('input'); | ||
expect(inputs.length).toBe(1); | ||
expect(inputs.eq(0).attr('type')).toBe('text'); | ||
expect(inputs.eq(0).attr('ng-model')).not.toBeUndefined(); | ||
expect(inputs.eq(0).attr('name')).toBe('username'); | ||
}); | ||
it('should databind ngTableParams.filter to filter input', function () { | ||
scope.tableParams.filter()['username'] = 'my name is...'; | ||
scope.$digest(); | ||
var input = elm.find('thead').find('tr').eq(1).find('th').find('input'); | ||
expect(input.val()).toBe('my name is...'); | ||
}); | ||
it('should make filter def available on $column', function () { | ||
expect($capturedColumn).toBeDefined(); | ||
expect($capturedColumn.filter).toBeDefined(); | ||
expect($capturedColumn.filter()['username']).toBe('text'); | ||
}); | ||
it('when filter changes should reset page number to 1', inject(function ($timeout) { | ||
// trigger initial load of data so that subsequent changes to filter will trigger reset of page # | ||
scope.tableParams.filter()['username'] = 'initial value'; | ||
scope.$digest(); | ||
$timeout.flush(); // trigger delayed filter | ||
// set page to something other than 1 | ||
scope.tableParams.page(5); | ||
expect(scope.tableParams.page()).toBe(5); // checking assumptions | ||
// when | ||
scope.tableParams.filter()['username'] = 'new value'; | ||
scope.$digest(); | ||
$timeout.flush(); // trigger delayed filter | ||
expect(scope.tableParams.page()).toBe(1); | ||
})); | ||
}); | ||
describe('filter specified with url', function(){ | ||
var elm; | ||
beforeEach(inject(function($compile, NgTableParams) { | ||
elm = angular.element( | ||
'<div>' + | ||
'<script type="text/ng-template" id="ng-table/filters/customNum.html"><input type="number" id="{{name}}"/></script>' + | ||
'<table ng-table="tableParams" show-filter="true">' + | ||
'<tr ng-repeat="user in $data">' + | ||
'<td header-class="captureColumn($column)" title="\'Age\'" ' + | ||
'filter="{ \'age\': \'ng-table/filters/customNum.html\' }">{{user.age}}</td>' + | ||
'</tr>' + | ||
'</table>' + | ||
'</div>'); | ||
$compile(elm)(scope); | ||
scope.tableParams = new NgTableParams({}, {}); | ||
scope.$digest(); | ||
})); | ||
it('should render filter template specified by url', function() { | ||
var inputs = elm.find('thead').find('tr').eq(1).find('th').find('input'); | ||
expect(inputs.length).toBe(1); | ||
expect(inputs.eq(0).attr('type')).toBe('number'); | ||
expect(inputs.eq(0).attr('id')).toBe('age'); | ||
}); | ||
}); | ||
describe('multiple filter inputs', function(){ | ||
var elm; | ||
beforeEach(inject(function($compile, NgTableParams) { | ||
elm = angular.element( | ||
'<div>' + | ||
'<table ng-table="tableParams" show-filter="true">' + | ||
'<tr ng-repeat="user in $data">' + | ||
'<td header-class="captureColumn($column)" title="\'Name\'" ' + | ||
'filter="{ \'name\': \'text\', \'age\': \'text\' }">{{user.name}}</td>' + | ||
'</tr>' + | ||
'</table>' + | ||
'</div>'); | ||
$compile(elm)(scope); | ||
scope.$digest(); | ||
scope.tableParams = new NgTableParams({}, {}); | ||
scope.$digest(); | ||
})); | ||
it('should render filter template for each key/value pair ordered by key', function() { | ||
var inputs = elm.find('thead').find('tr').eq(1).find('th').find('input'); | ||
expect(inputs.length).toBe(2); | ||
expect(inputs.eq(0).attr('type')).toBe('text'); | ||
expect(inputs.eq(0).attr('ng-model')).not.toBeUndefined(); | ||
expect(inputs.eq(1).attr('type')).toBe('text'); | ||
expect(inputs.eq(1).attr('ng-model')).not.toBeUndefined(); | ||
}); | ||
it('should databind ngTableParams.filter to filter inputs', function () { | ||
scope.tableParams.filter()['name'] = 'my name is...'; | ||
scope.tableParams.filter()['age'] = '10'; | ||
scope.$digest(); | ||
var inputs = elm.find('thead').find('tr').eq(1).find('th').find('input'); | ||
expect(inputs.eq(1).val()).toBe('my name is...'); | ||
expect(inputs.eq(0).val()).toBe('10'); | ||
}); | ||
it('should make filter def available on $column', function () { | ||
expect($capturedColumn).toBeDefined(); | ||
expect($capturedColumn.filter).toBeDefined(); | ||
expect($capturedColumn.filter()['name']).toBe('text'); | ||
expect($capturedColumn.filter()['age']).toBe('text'); | ||
}); | ||
}); | ||
describe('dynamic filter', function(){ | ||
var elm, ageFilter; | ||
beforeEach(inject(function($compile, NgTableParams) { | ||
ageFilter = {age: 'text'}; | ||
elm = angular.element( | ||
'<div>' + | ||
'<script type="text/ng-template" id="ng-table/filters/number.html"><input type="number" name="{{name}}"/></script>' + | ||
'<table ng-table="tableParams" show-filter="true">' + | ||
'<tr ng-repeat="user in $data">' + | ||
'<td title="\'Name\'" filter="getFilter($column)">{{user.name}}</td>' + | ||
'<td title="\'Age\'" filter="getFilter($column)">{{user.age}}</td>' + | ||
'</tr>' + | ||
'</table>' + | ||
'</div>'); | ||
$compile(elm)(scope); | ||
scope.$digest(); | ||
scope.getFilter = function(colDef){ | ||
if (colDef.id === 0) { | ||
return {username: 'text'}; | ||
} else if (colDef.id === 1) { | ||
return ageFilter; | ||
} | ||
}; | ||
scope.tableParams = new NgTableParams({}, {}); | ||
scope.$digest(); | ||
})); | ||
it('should render named filter template', function() { | ||
var usernameInput = elm.find('thead').find('tr').eq(1).find('th').eq(0).find('input'); | ||
expect(usernameInput.attr('type')).toBe('text'); | ||
expect(usernameInput.attr('name')).toBe('username'); | ||
var ageInput = elm.find('thead').find('tr').eq(1).find('th').eq(1).find('input'); | ||
expect(ageInput.attr('type')).toBe('text'); | ||
expect(ageInput.attr('name')).toBe('age'); | ||
}); | ||
it('should databind ngTableParams.filter to filter input', function () { | ||
scope.tableParams.filter()['username'] = 'my name is...'; | ||
scope.tableParams.filter()['age'] = '10'; | ||
scope.$digest(); | ||
var usernameInput = elm.find('thead').find('tr').eq(1).find('th').eq(0).find('input'); | ||
expect(usernameInput.val()).toBe('my name is...'); | ||
var ageInput = elm.find('thead').find('tr').eq(1).find('th').eq(1).find('input'); | ||
expect(ageInput.val()).toBe('10'); | ||
}); | ||
it('should render new template as filter changes', function() { | ||
ageFilter.age = 'number'; | ||
scope.$digest(); | ||
var ageInput = elm.find('thead').find('tr').eq(1).find('th').eq(1).find('input'); | ||
expect(ageInput.attr('type')).toBe('number'); | ||
expect(ageInput.attr('name')).toBe('age'); | ||
}); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
934002
22
88
7627
73
4