diff --git a/demos/tooltip.html b/demos/tooltip.html
index 7d11fc0..d5bdfee 100644
--- a/demos/tooltip.html
+++ b/demos/tooltip.html
@@ -56,7 +56,7 @@
System.import('components/popover/popover')
]).then(function(modules) {
- var module = angular.module('app', [ 'data-table', 'popover' ]);
+ var module = angular.module('app', [ 'data-table', 'dt.popover' ]);
module.controller('HomeController', function($scope, $http){
$scope.options = {
@@ -65,26 +65,26 @@
headerHeight: 50,
scrollbarV: true,
columns: [
- {
- name: "Company",
- prop: "company",
+ {
+ name: "Company",
+ prop: "company",
flexGrow: 2
},
- {
- name: "Revenue",
+ {
+ name: "Revenue",
flexGrow: 1,
- prop: "revenue"
+ prop: "revenue"
},
- {
- name: "Sales",
+ {
+ name: "Sales",
flexGrow: 1,
prop: "sales"
- },{
- name: "Comments",
+ },{
+ name: "Comments",
prop: "comments",
tooltips: true,
cellRenderer: function(scope, elm){
- return "{{value}} ";
+ return "{{$row.comments}} ";
}
diff --git a/gulpfile.js b/gulpfile.js
index c0e4373..d12d6da 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -123,7 +123,7 @@ gulp.task('release-build', function () {
}).then(function (bundle) {
return bundle.write({
dest: 'release/dataTable.es6.js',
- format: 'es6',
+ format: 'es',
moduleName: 'DataTable'
});
});
diff --git a/release/dataTable.cjs.js b/release/dataTable.cjs.js
index cb34ff8..f5acd01 100644
--- a/release/dataTable.cjs.js
+++ b/release/dataTable.cjs.js
@@ -6,20 +6,19 @@
*/
"use strict";
-DataTableDirective.$inject = ["$window", "$timeout", "$parse"];
-ResizableDirective.$inject = ["$document", "$timeout"];
-SortableDirective.$inject = ["$timeout"];
-HeaderDirective.$inject = ["$timeout"];
-HeaderCellDirective.$inject = ["$compile"];
-BodyDirective.$inject = ["$timeout"];
-ScrollerDirective.$inject = ["$timeout", "$rootScope"];
-CellDirective.$inject = ["$rootScope", "$compile", "$log", "$timeout"];
Object.defineProperty(exports, "__esModule", {
value: true
});
+exports.dtMenu = exports.dtPopover = undefined;
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+var _angular = require("angular");
+
+var _angular2 = _interopRequireDefault(_angular);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
@@ -62,308 +61,289 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
}
})();
-var PagerController = function () {
- PagerController.$inject = ["$scope"];
- function PagerController($scope) {
- var _this = this;
+function ResizableDirective($document, $timeout) {
+ return {
+ restrict: 'A',
+ scope: {
+ isResizable: '=resizable',
+ minWidth: '=',
+ maxWidth: '=',
+ onResize: '&'
+ },
+ link: function link($scope, $element, $attrs) {
+ if ($scope.isResizable) {
+ $element.addClass('resizable');
+ }
- _classCallCheck(this, PagerController);
+ var handle = angular.element(" "),
+ parent = $element.parent(),
+ prevScreenX;
- $scope.$watch('pager.count', function (newVal) {
- _this.calcTotalPages(_this.size, _this.count);
- _this.getPages(_this.page || 1);
- });
+ handle.on('mousedown', function (event) {
+ if (!$element[0].classList.contains('resizable')) {
+ return false;
+ }
- $scope.$watch('pager.size', function (newVal) {
- _this.calcTotalPages(_this.size, _this.count);
- _this.getPages(_this.page || 1);
- });
+ event.stopPropagation();
+ event.preventDefault();
- $scope.$watch('pager.page', function (newVal) {
- if (newVal !== 0 && newVal <= _this.totalPages) {
- _this.getPages(newVal);
+ $document.on('mousemove', mousemove);
+ $document.on('mouseup', mouseup);
+ });
+
+ function mousemove(event) {
+ event = event.originalEvent || event;
+
+ var width = parent[0].clientWidth,
+ movementX = event.movementX || event.mozMovementX || event.screenX - prevScreenX,
+ newWidth = width + (movementX || 0);
+
+ prevScreenX = event.screenX;
+
+ if ((!$scope.minWidth || newWidth >= $scope.minWidth) && (!$scope.maxWidth || newWidth <= $scope.maxWidth)) {
+ parent.css({
+ width: newWidth + 'px'
+ });
+ }
}
- });
- this.getPages(this.page || 1);
- }
+ function mouseup() {
+ if ($scope.onResize) {
+ $timeout(function () {
+ var width = parent[0].clientWidth;
+ if (width < $scope.minWidth) {
+ width = $scope.minWidth;
+ }
+ $scope.onResize({ width: width });
+ });
+ }
- _createClass(PagerController, [{
- key: "calcTotalPages",
- value: function calcTotalPages(size, count) {
- var count = size < 1 ? 1 : Math.ceil(count / size);
- this.totalPages = Math.max(count || 0, 1);
- }
- }, {
- key: "selectPage",
- value: function selectPage(num) {
- if (num > 0 && num <= this.totalPages) {
- this.page = num;
- this.onPage({
- page: num
- });
+ $document.unbind('mousemove', mousemove);
+ $document.unbind('mouseup', mouseup);
}
+
+ $element.append(handle);
}
- }, {
- key: "prevPage",
- value: function prevPage() {
- if (this.page > 1) {
- this.selectPage(--this.page);
+ };
+}
+
+function SortableDirective($timeout) {
+ return {
+ restrict: 'A',
+ scope: {
+ isSortable: '=sortable',
+ onSortableSort: '&'
+ },
+ link: function link($scope, $element, $attrs) {
+ var rootEl = $element[0],
+ dragEl,
+ nextEl,
+ dropEl;
+
+ function isbefore(a, b) {
+ if (a.parentNode == b.parentNode) {
+ for (var cur = a; cur; cur = cur.previousSibling) {
+ if (cur === b) {
+ return true;
+ }
+ }
+ }
+ return false;
}
- }
- }, {
- key: "nextPage",
- value: function nextPage() {
- this.selectPage(++this.page);
- }
- }, {
- key: "canPrevious",
- value: function canPrevious() {
- return this.page > 1;
- }
- }, {
- key: "canNext",
- value: function canNext() {
- return this.page < this.totalPages;
- }
- }, {
- key: "getPages",
- value: function getPages(page) {
- var pages = [],
- startPage = 1,
- endPage = this.totalPages,
- maxSize = 5,
- isMaxSized = maxSize < this.totalPages;
- if (isMaxSized) {
- startPage = (Math.ceil(page / maxSize) - 1) * maxSize + 1;
- endPage = Math.min(startPage + maxSize - 1, this.totalPages);
+ function onDragEnter(e) {
+ var target = e.target;
+ if (isbefore(dragEl, target)) {
+ target.parentNode.insertBefore(dragEl, target);
+ } else if (target.nextSibling && target.hasAttribute('draggable')) {
+ target.parentNode.insertBefore(dragEl, target.nextSibling.nextSibling);
+ }
}
- for (var number = startPage; number <= endPage; number++) {
- pages.push({
- number: number,
- text: number,
- active: number === page
- });
+ function onDragEnd(evt) {
+ evt.preventDefault();
+
+ dragEl.classList.remove('dt-clone');
+
+ $element.off('dragend', onDragEnd);
+ $element.off('dragenter', onDragEnter);
+
+ if (nextEl !== dragEl.nextSibling) {
+ $scope.onSortableSort({
+ event: evt,
+ columnId: _angular2.default.element(dragEl).attr('data-id')
+ });
+ }
}
- this.pages = pages;
- }
- }]);
+ function onDragStart(evt) {
+ if (!$scope.isSortable) return false;
+ evt = evt.originalEvent || evt;
- return PagerController;
-}();
+ dragEl = evt.target;
+ nextEl = dragEl.nextSibling;
+ dragEl.classList.add('dt-clone');
-function PagerDirective() {
- return {
- restrict: 'E',
- controller: PagerController,
- controllerAs: 'pager',
- scope: true,
- bindToController: {
- page: '=',
- size: '=',
- count: '=',
- onPage: '&'
- },
- template: "
",
- replace: true
+ evt.dataTransfer.effectAllowed = 'move';
+ evt.dataTransfer.setData('Text', dragEl.textContent);
+
+ $element.on('dragenter', onDragEnter);
+ $element.on('dragend', onDragEnd);
+ }
+
+ $element.on('dragstart', onDragStart);
+
+ $scope.$on('$destroy', function () {
+ $element.off('dragstart', onDragStart);
+ });
+ }
};
}
-var FooterController = function () {
- FooterController.$inject = ["$scope"];
- function FooterController($scope) {
- var _this2 = this;
+var TableDefaults = {
+ scrollbarV: true,
- _classCallCheck(this, FooterController);
+ rowHeight: 30,
- this.page = this.paging.offset + 1;
- $scope.$watch('footer.paging.offset', function (newVal) {
- _this2.offsetChanged(newVal);
- });
- }
+ columnMode: 'standard',
- _createClass(FooterController, [{
- key: "offsetChanged",
- value: function offsetChanged(newVal) {
- this.page = newVal + 1;
- }
- }, {
- key: "onPaged",
- value: function onPaged(page) {
- this.paging.offset = page - 1;
- this.onPage({
- offset: this.paging.offset,
- size: this.paging.size
- });
- }
- }]);
+ loadingMessage: 'Loading...',
- return FooterController;
-}();
+ emptyMessage: 'No data to display',
-function FooterDirective() {
- return {
- restrict: 'E',
- controller: FooterController,
- controllerAs: 'footer',
- scope: true,
- bindToController: {
- paging: '=',
- onPage: '&'
- },
- template: "",
- replace: true
- };
-}
+ headerHeight: 30,
-var CellController = function () {
- function CellController() {
- _classCallCheck(this, CellController);
- }
+ footerHeight: 0,
- _createClass(CellController, [{
- key: "styles",
- value: function styles() {
- return {
- width: this.column.width + 'px',
- 'min-width': this.column.width + 'px'
- };
- }
- }, {
- key: "cellClass",
- value: function cellClass() {
- var style = {
- 'dt-tree-col': this.column.isTreeColumn
- };
+ paging: {
+ externalPaging: false,
- if (this.column.className) {
- style[this.column.className] = true;
- }
+ size: undefined,
- return style;
- }
- }, {
- key: "treeClass",
- value: function treeClass() {
- return {
- 'dt-tree-toggle': true,
- 'icon-right': !this.expanded,
- 'icon-down': this.expanded
- };
- }
- }, {
- key: "onTreeToggled",
- value: function onTreeToggled(evt) {
- evt.stopPropagation();
- this.expanded = !this.expanded;
- this.onTreeToggle({
- cell: {
- value: this.value,
- column: this.column,
- expanded: this.expanded
- }
- });
- }
- }, {
- key: "onCheckboxChanged",
- value: function onCheckboxChanged(event) {
- event.stopPropagation();
- this.onCheckboxChange({ $event: event });
- }
- }, {
- key: "getValue",
- value: function getValue() {
- var val = this.column.cellDataGetter ? this.column.cellDataGetter(this.value) : this.value;
+ count: 0,
- if (val === undefined || val === null) val = '';
- return val;
- }
- }]);
+ offset: 0,
- return CellController;
-}();
+ loadingIndicator: false
+ },
-function CellDirective($rootScope, $compile, $log, $timeout) {
- return {
- restrict: 'E',
- controller: CellController,
- scope: true,
- controllerAs: 'cell',
- bindToController: {
- options: '=',
- value: '=',
- selected: '=',
- column: '=',
- row: '=',
- expanded: '=',
- hasChildren: '=',
- onTreeToggle: '&',
- onCheckboxChange: '&'
- },
- template: "\n \n \n \n \n \n
",
- replace: true,
- compile: function compile() {
- return {
- pre: function pre($scope, $elm, $attrs, ctrl) {
- var content = angular.element($elm[0].querySelector('.dt-cell-content')),
- cellScope;
+ selectable: false,
- if (ctrl.column.template || ctrl.column.cellRenderer) {
- createCellScope();
- }
+ multiSelect: false,
- $scope.$watch('cell.row', function () {
- if (cellScope) {
- cellScope.$destroy();
+ checkboxSelection: false,
- createCellScope();
+ reorderable: true,
- cellScope.$cell = ctrl.value;
- cellScope.$row = ctrl.row;
- cellScope.$column = ctrl.column;
- cellScope.$$watchers = null;
- }
+ internal: {
+ offsetX: 0,
+ offsetY: 0,
+ innerWidth: 0,
+ bodyHeight: 300
+ }
- if (ctrl.column.template) {
- content.empty();
- var elm = angular.element("" + ctrl.column.template.trim() + " ");
- content.append($compile(elm)(cellScope));
- } else if (ctrl.column.cellRenderer) {
- content.empty();
- var elm = angular.element(ctrl.column.cellRenderer(cellScope, content));
- content.append($compile(elm)(cellScope));
- } else {
- content[0].innerHTML = ctrl.getValue();
- }
- }, true);
+};
- function createCellScope() {
- cellScope = ctrl.options.$outer.$new(false);
- cellScope.getValue = ctrl.getValue;
- }
- }
- };
- }
+var ColumnDefaults = {
+ frozenLeft: false,
+
+ frozenRight: false,
+
+ className: undefined,
+
+ headerClassName: undefined,
+
+ flexGrow: 0,
+
+ minWidth: 100,
+
+ maxWidth: undefined,
+
+ width: 150,
+
+ resizable: true,
+
+ comparator: undefined,
+
+ sortable: true,
+
+ sort: undefined,
+
+ sortBy: undefined,
+
+ headerRenderer: undefined,
+
+ cellRenderer: undefined,
+
+ cellDataGetter: undefined,
+
+ isTreeColumn: false,
+
+ isCheckboxColumn: false,
+
+ headerCheckbox: false,
+
+ canAutoResize: true
+
+};
+
+var requestAnimFrame = function () {
+ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {
+ window.setTimeout(callback, 1000 / 60);
};
+}();
+
+function ObjectId() {
+ var timestamp = (new Date().getTime() / 1000 | 0).toString(16);
+ return timestamp + 'xxxxxxxxxxxxxxxx'.replace(/[x]/g, function () {
+ return (Math.random() * 16 | 0).toString(16);
+ }).toLowerCase();
}
-var cache = {},
- testStyle = document.createElement('div').style;
+function ColumnsByPin(cols) {
+ var ret = {
+ left: [],
+ center: [],
+ right: []
+ };
-var prefix = function () {
- var styles = window.getComputedStyle(document.documentElement, ''),
- pre = (Array.prototype.slice.call(styles).join('').match(/-(moz|webkit|ms)-/) || styles.OLink === '' && ['', 'o'])[1],
- dom = 'WebKit|Moz|MS|O'.match(new RegExp('(' + pre + ')', 'i'))[1];
+ for (var i = 0, len = cols.length; i < len; i++) {
+ var c = cols[i];
+ if (c.frozenLeft) {
+ ret.left.push(c);
+ } else if (c.frozenRight) {
+ ret.right.push(c);
+ } else {
+ ret.center.push(c);
+ }
+ }
+
+ return ret;
+}
+
+function ColumnGroupWidths(groups, all) {
return {
- dom: dom,
- lowercase: pre,
- css: '-' + pre + '-',
- js: pre[0].toUpperCase() + pre.substr(1)
+ left: ColumnTotalWidth(groups.left),
+ center: ColumnTotalWidth(groups.center),
+ right: ColumnTotalWidth(groups.right),
+ total: ColumnTotalWidth(all)
};
-}();
+}
+
+function DeepValueGetter(obj, path) {
+ if (!obj || !path) return obj;
+
+ var current = obj,
+ split = path.split('.');
+
+ if (split.length) {
+ for (var i = 0, len = split.length; i < len; i++) {
+ current = current[split[i]];
+ }
+ }
+
+ return current;
+}
function CamelCase(str) {
str = str.replace(/[^a-zA-Z0-9 ]/g, " ");
@@ -378,2020 +358,2441 @@ function CamelCase(str) {
return str;
}
-function GetVendorPrefixedName(property) {
- var name = CamelCase(property);
- if (!cache[name]) {
- if (testStyle[prefix.css + property] !== undefined) {
- cache[name] = prefix.css + property;
- } else if (testStyle[property] !== undefined) {
- cache[name] = property;
- }
- }
- return cache[name];
-}
+function ScrollbarWidth() {
+ var outer = document.createElement("div");
+ outer.style.visibility = "hidden";
+ outer.style.width = "100px";
+ outer.style.msOverflowStyle = "scrollbar";
+ document.body.appendChild(outer);
-var transform = GetVendorPrefixedName('transform'),
- backfaceVisibility = GetVendorPrefixedName('backfaceVisibility'),
- hasCSSTransforms = !!GetVendorPrefixedName('transform'),
- hasCSS3DTransforms = !!GetVendorPrefixedName('perspective'),
- ua = window.navigator.userAgent,
- isSafari = /Safari\//.test(ua) && !/Chrome\//.test(ua);
+ var widthNoScroll = outer.offsetWidth;
+ outer.style.overflow = "scroll";
-function TranslateXY(styles, x, y) {
- if (hasCSSTransforms) {
- if (!isSafari && hasCSS3DTransforms) {
- styles[transform] = "translate3d(" + x + "px, " + y + "px, 0)";
- styles[backfaceVisibility] = 'hidden';
- } else {
- styles[CamelCase(transform)] = "translate(" + x + "px, " + y + "px)";
- }
- } else {
- styles.top = y + 'px';
- styles.left = x + 'px';
- }
-}
+ var inner = document.createElement("div");
+ inner.style.width = "100%";
+ outer.appendChild(inner);
-var GroupRowController = function () {
- function GroupRowController() {
- _classCallCheck(this, GroupRowController);
- }
+ var widthWithScroll = inner.offsetWidth;
+ outer.parentNode.removeChild(outer);
- _createClass(GroupRowController, [{
- key: "onGroupToggled",
- value: function onGroupToggled(evt) {
- evt.stopPropagation();
- this.onGroupToggle({
- group: this.row
- });
+ return widthNoScroll - widthWithScroll;
+}
+
+function NextSortDirection(sortType, currentSort) {
+ if (sortType === 'single') {
+ if (currentSort === 'asc') {
+ return 'desc';
+ } else {
+ return 'asc';
}
- }, {
- key: "treeClass",
- value: function treeClass() {
- return {
- 'dt-tree-toggle': true,
- 'icon-right': !this.expanded,
- 'icon-down': this.expanded
- };
+ } else {
+ if (!currentSort) {
+ return 'asc';
+ } else if (currentSort === 'asc') {
+ return 'desc';
+ } else if (currentSort === 'desc') {
+ return undefined;
}
- }]);
+ }
+}
- return GroupRowController;
-}();
+function ColumnTotalWidth(columns, prop) {
+ var totalWidth = 0;
-function GroupRowDirective() {
- return {
- restrict: 'E',
- controller: GroupRowController,
- controllerAs: 'group',
- bindToController: {
- row: '=',
- onGroupToggle: '&',
- expanded: '=',
- options: '='
- },
- scope: true,
- replace: true,
- template: "\n \n \n \n \n \n
",
- link: function link($scope, $elm, $attrs, ctrl) {
- TranslateXY($elm[0].style, 0, ctrl.row.$$index * ctrl.options.rowHeight);
+ columns.forEach(function (c) {
+ var has = prop && c[prop];
+ totalWidth = totalWidth + (has ? c[prop] : c.width);
+ });
- ctrl.options.internal.styleTranslator.register($scope.$index, $elm);
- }
- };
+ return totalWidth;
}
-function DeepValueGetter(obj, path) {
- if (!obj || !path) return obj;
+function GetTotalFlexGrow(columns) {
+ var totalFlexGrow = 0;
- var current = obj,
- split = path.split('.');
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
- if (split.length) {
- for (var i = 0, len = split.length; i < len; i++) {
- current = current[split[i]];
+ try {
+ for (var _iterator = columns[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ var c = _step.value;
+
+ totalFlexGrow += c.flexGrow || 0;
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
}
}
- return current;
+ return totalFlexGrow;
}
-var RowController = function () {
- function RowController() {
- _classCallCheck(this, RowController);
- }
+function AdjustColumnWidths(allColumns, expectedWidth) {
+ var columnsWidth = ColumnTotalWidth(allColumns),
+ totalFlexGrow = GetTotalFlexGrow(allColumns),
+ colsByGroup = ColumnsByPin(allColumns);
- _createClass(RowController, [{
- key: "getValue",
- value: function getValue(col) {
- if (!col.prop) return '';
- return DeepValueGetter(this.row, col.prop);
- }
- }, {
- key: "onTreeToggled",
- value: function onTreeToggled(cell) {
- this.onTreeToggle({
- cell: cell,
- row: this.row
- });
- }
- }, {
- key: "stylesByGroup",
- value: function stylesByGroup(group) {
- var styles = {
- width: this.columnWidths[group] + 'px'
- };
+ if (columnsWidth !== expectedWidth) {
+ ScaleColumns(colsByGroup, expectedWidth, totalFlexGrow);
+ }
+}
- if (group === 'left') {
- TranslateXY(styles, this.options.internal.offsetX, 0);
- } else if (group === 'right') {
- var offset = (this.columnWidths.total - this.options.internal.innerWidth - this.options.internal.offsetX + this.options.internal.scrollBarWidth) * -1;
- TranslateXY(styles, offset, 0);
+function ScaleColumns(colsByGroup, maxWidth, totalFlexGrow) {
+ _angular2.default.forEach(colsByGroup, function (cols) {
+ cols.forEach(function (column) {
+ if (!column.canAutoResize) {
+ maxWidth -= column.width;
+ totalFlexGrow -= column.flexGrow;
+ } else {
+ column.width = 0;
}
+ });
+ });
- return styles;
- }
- }, {
- key: "onCheckboxChanged",
- value: function onCheckboxChanged(ev) {
- this.onCheckboxChange({
- $event: ev,
- row: this.row
+ var hasMinWidth = {};
+ var remainingWidth = maxWidth;
+
+ var _loop = function _loop() {
+ var widthPerFlexPoint = remainingWidth / totalFlexGrow;
+ remainingWidth = 0;
+ _angular2.default.forEach(colsByGroup, function (cols) {
+ cols.forEach(function (column, i) {
+ if (column.canAutoResize && !hasMinWidth[i]) {
+ var newWidth = column.width + column.flexGrow * widthPerFlexPoint;
+ if (column.minWidth !== undefined && newWidth < column.minWidth) {
+ remainingWidth += newWidth - column.minWidth;
+ column.width = column.minWidth;
+ hasMinWidth[i] = true;
+ } else {
+ column.width = newWidth;
+ }
+ }
});
+ });
+ };
+
+ do {
+ _loop();
+ } while (remainingWidth !== 0);
+}
+
+function ForceFillColumnWidths(allColumns, expectedWidth, startIdx) {
+ var contentWidth = 0,
+ columnsToResize = startIdx > -1 ? allColumns.slice(startIdx, allColumns.length).filter(function (c) {
+ return c.canAutoResize;
+ }) : allColumns.filter(function (c) {
+ return c.canAutoResize;
+ });
+
+ allColumns.forEach(function (c) {
+ if (!c.canAutoResize) {
+ contentWidth += c.width;
+ } else {
+ contentWidth += c.$$oldWidth || c.width;
}
- }]);
+ });
- return RowController;
-}();
+ var remainingWidth = expectedWidth - contentWidth,
+ additionWidthPerColumn = remainingWidth / columnsToResize.length,
+ exceedsWindow = contentWidth > expectedWidth;
-function RowDirective() {
- return {
- restrict: 'E',
- controller: RowController,
- controllerAs: 'rowCtrl',
- scope: true,
- bindToController: {
- row: '=',
- columns: '=',
- columnWidths: '=',
- expanded: '=',
- selected: '=',
- hasChildren: '=',
- options: '=',
- onCheckboxChange: '&',
- onTreeToggle: '&'
- },
- link: function link($scope, $elm, $attrs, ctrl) {
- if (ctrl.row) {
- TranslateXY($elm[0].style, 0, ctrl.row.$$index * ctrl.options.rowHeight);
+ columnsToResize.forEach(function (column) {
+ if (exceedsWindow) {
+ column.width = column.$$oldWidth || column.width;
+ } else {
+ if (!column.$$oldWidth) {
+ column.$$oldWidth = column.width;
}
- ctrl.options.internal.styleTranslator.register($scope.$index, $elm);
- },
- template: "\n \n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
",
- replace: true
- };
+ var newSize = column.$$oldWidth + additionWidthPerColumn;
+ if (column.minWith && newSize < column.minWidth) {
+ column.width = column.minWidth;
+ } else if (column.maxWidth && newSize > column.maxWidth) {
+ column.width = column.maxWidth;
+ } else {
+ column.width = newSize;
+ }
+ }
+ });
}
-var KEYS = {
- BACKSPACE: 8,
- TAB: 9,
- RETURN: 13,
- ALT: 18,
- ESC: 27,
- SPACE: 32,
- PAGE_UP: 33,
- PAGE_DOWN: 34,
- END: 35,
- HOME: 36,
- LEFT: 37,
- UP: 38,
- RIGHT: 39,
- DOWN: 40,
- DELETE: 46,
- COMMA: 188,
- PERIOD: 190,
- A: 65,
- Z: 90,
- ZERO: 48,
- NUMPAD_0: 96,
- NUMPAD_9: 105
-};
+var DataTableController = function () {
+ function DataTableController($scope, $filter, $log, $transclude) {
+ var _this = this;
-var SelectionController = function () {
- SelectionController.$inject = ["$scope"];
- function SelectionController($scope) {
- _classCallCheck(this, SelectionController);
+ _classCallCheck(this, DataTableController);
- this.body = $scope.body;
- this.options = $scope.body.options;
- this.selected = $scope.body.selected;
- }
+ Object.assign(this, {
+ $scope: $scope,
+ $filter: $filter,
+ $log: $log
+ });
- _createClass(SelectionController, [{
- key: "keyDown",
- value: function keyDown(ev, index, row) {
- if (KEYS[ev.keyCode]) {
- ev.preventDefault();
+ this.defaults();
+
+ this.options.$outer = $scope.$parent;
+
+ $scope.$watch('dt.options.columns', function (newVal, oldVal) {
+ _this.transposeColumnDefaults();
+
+ if (newVal.length !== oldVal.length) {
+ _this.adjustColumns();
}
- if (ev.keyCode === KEYS.DOWN) {
- var next = ev.target.nextElementSibling;
- if (next) {
- next.focus();
- }
- } else if (ev.keyCode === KEYS.UP) {
- var prev = ev.target.previousElementSibling;
- if (prev) {
- prev.focus();
+ _this.calculateColumns();
+ }, true);
+
+ var watch = $scope.$watch('dt.rows', function (newVal) {
+ if (newVal) {
+ watch();
+ _this.onSorted();
+ }
+ });
+ }
+
+ _createClass(DataTableController, [{
+ key: "defaults",
+ value: function defaults() {
+ var _this2 = this;
+
+ this.expanded = this.expanded || {};
+
+ this.options = _angular2.default.extend(_angular2.default.copy(TableDefaults), this.options);
+
+ _angular2.default.forEach(TableDefaults.paging, function (v, k) {
+ if (!_this2.options.paging[k]) {
+ _this2.options.paging[k] = v;
}
- } else if (ev.keyCode === KEYS.RETURN) {
- this.selectRow(index, row);
+ });
+
+ if (this.options.selectable && this.options.multiSelect) {
+ this.selected = this.selected || [];
}
}
}, {
- key: "rowClicked",
- value: function rowClicked(event, index, row) {
- if (!this.options.checkboxSelection) {
- this.selectRow(event, index, row);
- }
+ key: "transposeColumnDefaults",
+ value: function transposeColumnDefaults() {
+ for (var i = 0, len = this.options.columns.length; i < len; i++) {
+ var column = this.options.columns[i];
+ column.$id = ObjectId();
- this.body.onRowClick({ row: row });
+ _angular2.default.forEach(ColumnDefaults, function (v, k) {
+ if (!column.hasOwnProperty(k)) {
+ column[k] = v;
+ }
+ });
+
+ if (column.name && !column.prop) {
+ column.prop = CamelCase(column.name);
+ }
+
+ this.options.columns[i] = column;
+ }
}
}, {
- key: "rowDblClicked",
- value: function rowDblClicked(event, index, row) {
- if (!this.options.checkboxSelection) {
- event.preventDefault();
- this.selectRow(event, index, row);
- }
-
- this.body.onRowDblClick({ row: row });
+ key: "calculateColumns",
+ value: function calculateColumns() {
+ var columns = this.options.columns;
+ this.columnsByPin = ColumnsByPin(columns);
+ this.columnWidths = ColumnGroupWidths(this.columnsByPin, columns);
}
}, {
- key: "onCheckboxChange",
- value: function onCheckboxChange(event, index, row) {
- this.selectRow(event, index, row);
+ key: "tableCss",
+ value: function tableCss() {
+ return {
+ 'fixed': this.options.scrollbarV,
+ 'selectable': this.options.selectable,
+ 'checkboxable': this.options.checkboxSelection
+ };
}
}, {
- key: "selectRow",
- value: function selectRow(event, index, row) {
- if (this.options.selectable) {
- if (this.options.multiSelect) {
- var isCtrlKeyDown = event.ctrlKey || event.metaKey,
- isShiftKeyDown = event.shiftKey;
+ key: "adjustColumns",
+ value: function adjustColumns(forceIdx) {
+ var width = this.options.internal.innerWidth - this.options.internal.scrollBarWidth;
- if (isShiftKeyDown) {
- this.selectRowsBetween(index, row);
- } else {
- var idx = this.selected.indexOf(row);
- if (idx > -1) {
- this.selected.splice(idx, 1);
- } else {
- if (this.options.multiSelectOnShift && this.selected.length === 1) {
- this.selected.splice(0, 1);
- }
- this.selected.push(row);
- this.body.onSelect({ rows: [row] });
- }
- }
- this.prevIndex = index;
- } else {
- this.selected = row;
- this.body.onSelect({ rows: [row] });
- }
+ if (this.options.columnMode === 'force') {
+ ForceFillColumnWidths(this.options.columns, width, forceIdx);
+ } else if (this.options.columnMode === 'flex') {
+ AdjustColumnWidths(this.options.columns, width);
}
}
}, {
- key: "selectRowsBetween",
- value: function selectRowsBetween(index) {
- var reverse = index < this.prevIndex,
- selecteds = [];
-
- for (var i = 0, len = this.body.rows.length; i < len; i++) {
- var row = this.body.rows[i],
- greater = i >= this.prevIndex && i <= index,
- lesser = i <= this.prevIndex && i >= index;
+ key: "calculatePageSize",
+ value: function calculatePageSize() {
+ this.options.paging.size = Math.ceil(this.options.internal.bodyHeight / this.options.rowHeight) + 1;
+ }
+ }, {
+ key: "onSorted",
+ value: function onSorted() {
+ if (!this.rows) return;
- var range = {};
- if (reverse) {
- range = {
- start: index,
- end: this.prevIndex - index
- };
- } else {
- range = {
- start: this.prevIndex,
- end: index + 1
- };
+ var sorts = this.options.columns.filter(function (c) {
+ return c.sort;
+ }).sort(function (a, b) {
+ if (a.sortPriority && b.sortPriority) {
+ if (a.sortPriority > b.sortPriority) return 1;
+ if (a.sortPriority < b.sortPriority) return -1;
+ } else if (a.sortPriority) {
+ return -1;
+ } else if (b.sortPriority) {
+ return 1;
}
- if (reverse && lesser || !reverse && greater) {
- var idx = this.selected.indexOf(row);
+ return 0;
+ }).map(function (c, i) {
+ c.sortPriority = i + 1;
+ return c;
+ });
- if (reverse && idx > -1) {
- this.selected.splice(idx, 1);
- continue;
- }
+ if (sorts.length) {
+ this.onSort({ sorts: sorts });
- if (i >= range.start && i < range.end) {
- if (idx === -1) {
- this.selected.push(row);
- selecteds.push(row);
+ if (this.options.onSort) {
+ this.options.onSort(sorts);
+ }
+
+ var clientSorts = [];
+ for (var i = 0, len = sorts.length; i < len; i++) {
+ var c = sorts[i];
+ if (c.comparator !== false) {
+ var dir = c.sort === 'asc' ? '' : '-';
+ if (c.sortBy !== undefined) {
+ clientSorts.push(dir + c.sortBy);
+ } else {
+ clientSorts.push(dir + c.prop);
}
}
}
+
+ if (clientSorts.length) {
+ var _rows;
+
+ var sortedValues = this.$filter('orderBy')(this.rows, clientSorts);
+ this.rows.splice(0, this.rows.length);
+ (_rows = this.rows).push.apply(_rows, _toConsumableArray(sortedValues));
+ }
}
- this.body.onSelect({ rows: selecteds });
+ this.options.internal.setYOffset(0);
}
- }]);
-
- return SelectionController;
-}();
+ }, {
+ key: "onTreeToggled",
+ value: function onTreeToggled(row, cell) {
+ this.onTreeToggle({
+ row: row,
+ cell: cell
+ });
+ }
+ }, {
+ key: "onBodyPage",
+ value: function onBodyPage(offset, size) {
+ this.onPage({
+ offset: offset,
+ size: size
+ });
+ }
+ }, {
+ key: "onFooterPage",
+ value: function onFooterPage(offset, size) {
+ var pageBlockSize = this.options.rowHeight * size,
+ offsetY = pageBlockSize * offset;
-function SelectionDirective() {
- return {
- controller: SelectionController,
- restrict: 'A',
- require: '^dtBody',
- controllerAs: 'selCtrl'
- };
-}
-
-var requestAnimFrame = function () {
- return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {
- window.setTimeout(callback, 1000 / 60);
- };
-}();
-
-var StyleTranslator = function () {
- function StyleTranslator(height) {
- _classCallCheck(this, StyleTranslator);
+ this.options.internal.setYOffset(offsetY);
+ }
+ }, {
+ key: "onHeaderCheckboxChange",
+ value: function onHeaderCheckboxChange() {
+ if (this.rows) {
+ var matches = this.selected.length === this.rows.length;
+ this.selected.splice(0, this.selected.length);
- this.height = height;
- this.map = new Map();
- }
+ if (!matches) {
+ var _selected;
- _createClass(StyleTranslator, [{
- key: "update",
- value: function update(rows) {
- var n = 0;
- while (n <= this.map.size) {
- var dom = this.map.get(n);
- var model = rows[n];
- if (dom && model) {
- TranslateXY(dom[0].style, 0, model.$$index * this.height);
+ (_selected = this.selected).push.apply(_selected, _toConsumableArray(this.rows));
}
- n++;
}
}
}, {
- key: "register",
- value: function register(idx, dom) {
- this.map.set(idx, dom);
+ key: "isAllRowsSelected",
+ value: function isAllRowsSelected() {
+ if (this.rows) return false;
+ return this.selected.length === this.rows.length;
}
- }]);
-
- return StyleTranslator;
-}();
-
-function ScrollerDirective($timeout, $rootScope) {
- return {
- restrict: 'E',
- require: '^dtBody',
- transclude: true,
- replace: true,
- template: "
",
- link: function link($scope, $elm, $attrs, ctrl) {
- var ticking = false,
- lastScrollY = 0,
- lastScrollX = 0,
- parent = $elm.parent();
-
- ctrl.options.internal.styleTranslator = new StyleTranslator(ctrl.options.rowHeight);
-
- ctrl.options.internal.setYOffset = function (offsetY) {
- parent[0].scrollTop = offsetY;
- };
-
- function update() {
- ctrl.options.internal.offsetY = lastScrollY;
- ctrl.options.internal.offsetX = lastScrollX;
- ctrl.updatePage();
-
- if (ctrl.options.scrollbarV) {
- ctrl.getRows();
- }
-
- ctrl.options.$outer.$digest();
-
- ticking = false;
- };
+ }, {
+ key: "onResized",
+ value: function onResized(column, width) {
+ var idx = this.options.columns.indexOf(column);
+ if (idx > -1) {
+ var column = this.options.columns[idx];
+ column.width = width;
+ column.canAutoResize = false;
- function requestTick() {
- if (!ticking) {
- requestAnimFrame(update);
- ticking = true;
- }
- };
+ this.adjustColumns(idx);
+ this.calculateColumns();
+ }
- parent.on('scroll', function (ev) {
- lastScrollY = this.scrollTop;
- lastScrollX = this.scrollLeft;
- requestTick();
+ if (this.onColumnResize) {
+ this.onColumnResize({
+ column: column,
+ width: width
+ });
+ }
+ }
+ }, {
+ key: "onSelected",
+ value: function onSelected(rows) {
+ this.onSelect({
+ rows: rows
});
-
- $scope.$on('$destroy', function () {
- parent.off('scroll');
+ }
+ }, {
+ key: "onRowClicked",
+ value: function onRowClicked(row) {
+ this.onRowClick({
+ row: row
+ });
+ }
+ }, {
+ key: "onRowDblClicked",
+ value: function onRowDblClicked(row) {
+ this.onRowDblClick({
+ row: row
});
+ }
+ }]);
- $scope.scrollerStyles = function () {
- if (ctrl.options.scrollbarV) {
- return {
- height: ctrl.count * ctrl.options.rowHeight + 'px'
- };
- }
- };
+ return DataTableController;
+}();
+
+function throttle(func, wait, options) {
+ var context, args, result;
+ var timeout = null;
+ var previous = 0;
+ options || (options = {});
+ var later = function later() {
+ previous = options.leading === false ? 0 : new Date();
+ timeout = null;
+ result = func.apply(context, args);
+ };
+ return function () {
+ var now = new Date();
+ if (!previous && options.leading === false) previous = now;
+ var remaining = wait - (now - previous);
+ context = this;
+ args = arguments;
+ if (remaining <= 0) {
+ clearTimeout(timeout);
+ timeout = null;
+ previous = now;
+ result = func.apply(context, args);
+ } else if (!timeout && options.trailing !== false) {
+ timeout = setTimeout(later, remaining);
}
+ return result;
};
}
-var BodyController = function () {
- BodyController.$inject = ["$scope", "$timeout"];
- function BodyController($scope, $timeout) {
- var _this3 = this;
-
- _classCallCheck(this, BodyController);
+var DataTableService = {
+ columns: {},
+ dTables: {},
- this.$scope = $scope;
- this.tempRows = [];
+ saveColumns: function saveColumns(id, columnElms) {
+ if (columnElms && columnElms.length) {
+ var columnsArray = [].slice.call(columnElms);
+ this.dTables[id] = columnsArray;
+ }
+ },
+ buildColumns: function buildColumns(scope, parse) {
+ var _this3 = this;
- this.treeColumn = this.options.columns.find(function (c) {
- return c.isTreeColumn;
- });
+ _angular2.default.forEach(this.dTables, function (columnElms, id) {
+ _this3.columns[id] = [];
- this.groupColumn = this.options.columns.find(function (c) {
- return c.group;
- });
+ _angular2.default.forEach(columnElms, function (c) {
+ var column = {};
- $scope.$watchCollection('body.rows', this.rowsUpdated.bind(this));
+ var visible = true;
- if (this.options.scrollbarV || !this.options.scrollbarV && this.options.paging.externalPaging) {
- var sized = false;
- $scope.$watch('body.options.paging.size', function (newVal, oldVal) {
- if (!sized || newVal > oldVal) {
- _this3.getRows();
- sized = true;
- }
- });
+ _angular2.default.forEach(c.attributes, function (attr) {
+ var attrName = CamelCase(attr.name);
- $scope.$watch('body.options.paging.count', function (count) {
- _this3.count = count;
- _this3.updatePage();
- });
+ switch (attrName) {
+ case 'class':
+ column.className = attr.value;
+ break;
+ case 'name':
+ case 'prop':
+ column[attrName] = attr.value;
+ break;
+ case 'headerRenderer':
+ case 'cellRenderer':
+ case 'cellDataGetter':
+ column[attrName] = parse(attr.value);
+ break;
+ case 'visible':
+ visible = parse(attr.value)(scope);
+ break;
+ default:
+ column[attrName] = parse(attr.value)(scope);
+ break;
+ }
+ });
- $scope.$watch('body.options.paging.offset', function (newVal) {
- if (_this3.options.paging.size) {
- _this3.onPage({
- offset: newVal,
- size: _this3.options.paging.size
- });
+ var header = c.getElementsByTagName('column-header');
+ if (header.length) {
+ column.headerTemplate = header[0].innerHTML;
+ c.removeChild(header[0]);
}
- });
- }
- }
- _createClass(BodyController, [{
- key: "rowsUpdated",
- value: function rowsUpdated(newVal, oldVal) {
- if (newVal) {
- if (!this.options.paging.externalPaging) {
- this.options.paging.count = newVal.length;
+ if (c.innerHTML !== '') {
+ column.template = c.innerHTML;
}
- this.count = this.options.paging.count;
+ if (visible) _this3.columns[id].push(column);
+ });
+ });
- if (this.treeColumn || this.groupColumn) {
- this.buildRowsByGroup();
- }
+ this.dTables = {};
+ }
+};
- if (this.options.scrollbarV) {
- var refresh = newVal && oldVal && (newVal.length === oldVal.length || newVal.length < oldVal.length);
+function DataTableDirective($window, $timeout, $parse) {
+ return {
+ restrict: 'E',
+ replace: true,
+ controller: DataTableController,
+ scope: true,
+ bindToController: {
+ options: '=',
+ rows: '=',
+ selected: '=?',
+ expanded: '=?',
+ onSelect: '&',
+ onSort: '&',
+ onTreeToggle: '&',
+ onPage: '&',
+ onRowClick: '&',
+ onRowDblClick: '&',
+ onColumnResize: '&'
+ },
+ controllerAs: 'dt',
+ template: function template(element) {
+ var columns = element[0].getElementsByTagName('column'),
+ id = ObjectId();
+ DataTableService.saveColumns(id, columns);
- this.getRows(refresh);
- } else {
- var rows = this.rows;
+ return "\n \n \n \n \n \n \n
";
+ },
+ compile: function compile(tElem, tAttrs) {
+ return {
+ pre: function pre($scope, $elm, $attrs, ctrl) {
+ DataTableService.buildColumns($scope, $parse);
- if (this.treeColumn) {
- rows = this.buildTree();
- } else if (this.groupColumn) {
- rows = this.buildGroups();
+ var id = $elm.attr('data-column-id'),
+ columns = DataTableService.columns[id];
+ if (columns) {
+ ctrl.options.columns = columns;
}
- if (this.options.paging.externalPaging) {
- var idxs = this.getFirstLastIndexes(),
- idx = idxs.first;
+ ctrl.transposeColumnDefaults();
+ ctrl.options.internal.scrollBarWidth = ScrollbarWidth();
- this.tempRows.splice(0, this.tempRows.length);
- while (idx < idxs.last) {
- this.tempRows.push(rows[idx++]);
+ function resize() {
+ var rect = $elm[0].getBoundingClientRect();
+
+ ctrl.options.internal.innerWidth = Math.floor(rect.width);
+
+ if (ctrl.options.scrollbarV) {
+ var height = rect.height;
+
+ if (ctrl.options.headerHeight) {
+ height = height - ctrl.options.headerHeight;
+ }
+
+ if (ctrl.options.footerHeight) {
+ height = height - ctrl.options.footerHeight;
+ }
+
+ ctrl.options.internal.bodyHeight = height;
+ ctrl.calculatePageSize();
}
- } else {
- var _tempRows;
- this.tempRows.splice(0, this.tempRows.length);
- (_tempRows = this.tempRows).push.apply(_tempRows, _toConsumableArray(rows));
+ ctrl.adjustColumns();
}
+
+ $window.addEventListener('resize', throttle(function () {
+ $timeout(resize);
+ }));
+
+ var checkVisibility = function checkVisibility() {
+ var bounds = $elm[0].getBoundingClientRect(),
+ visible = bounds.width && bounds.height;
+ if (visible) resize();else $timeout(checkVisibility, 100);
+ };
+ checkVisibility();
+
+ $elm.addClass('dt-loaded');
+
+ $scope.$on('$destroy', function () {
+ _angular2.default.element($window).off('resize');
+ });
}
- }
+ };
}
- }, {
- key: "getFirstLastIndexes",
- value: function getFirstLastIndexes() {
- var firstRowIndex, endIndex;
+ };
+}
- if (this.options.scrollbarV) {
- firstRowIndex = Math.max(Math.floor((this.options.internal.offsetY || 0) / this.options.rowHeight, 0), 0);
- endIndex = Math.min(firstRowIndex + this.options.paging.size, this.count);
- } else {
- if (this.options.paging.externalPaging) {
- firstRowIndex = Math.max(this.options.paging.offset * this.options.paging.size, 0);
- endIndex = Math.min(firstRowIndex + this.options.paging.size, this.count);
- } else {
- endIndex = this.count;
- }
- }
+var cache = {};
+var testStyle = document.createElement('div').style;
- return {
- first: firstRowIndex,
- last: endIndex
- };
+var prefix = function () {
+ var styles = window.getComputedStyle(document.documentElement, ''),
+ pre = (Array.prototype.slice.call(styles).join('').match(/-(moz|webkit|ms)-/) || styles.OLink === '' && ['', 'o'])[1],
+ dom = 'WebKit|Moz|MS|O'.match(new RegExp('(' + pre + ')', 'i'))[1];
+ return {
+ dom: dom,
+ lowercase: pre,
+ css: '-' + pre + '-',
+ js: pre[0].toUpperCase() + pre.substr(1)
+ };
+}();
+
+function GetVendorPrefixedName(property) {
+ var name = CamelCase(property);
+ if (!cache[name]) {
+ if (testStyle[prefix.css + property] !== undefined) {
+ cache[name] = prefix.css + property;
+ } else if (testStyle[property] !== undefined) {
+ cache[name] = property;
}
- }, {
- key: "updatePage",
- value: function updatePage() {
- var curPage = this.options.paging.offset,
- idxs = this.getFirstLastIndexes();
+ }
+ return cache[name];
+}
- if (this.options.internal.oldScrollPosition === undefined) {
- this.options.internal.oldScrollPosition = 0;
- }
+var transform = GetVendorPrefixedName('transform');
+var backfaceVisibility = GetVendorPrefixedName('backfaceVisibility');
+var hasCSSTransforms = !!GetVendorPrefixedName('transform');
+var hasCSS3DTransforms = !!GetVendorPrefixedName('perspective');
+var ua = window.navigator.userAgent;
+var isSafari = /Safari\//.test(ua) && !/Chrome\//.test(ua);
- var oldScrollPosition = this.options.internal.oldScrollPosition,
- newPage = idxs.first / this.options.paging.size;
+function TranslateXY(styles, x, y) {
+ if (hasCSSTransforms) {
+ if (!isSafari && hasCSS3DTransforms) {
+ styles[transform] = "translate3d(" + x + "px, " + y + "px, 0)";
+ styles[backfaceVisibility] = 'hidden';
+ } else {
+ styles[CamelCase(transform)] = "translate(" + x + "px, " + y + "px)";
+ }
+ } else {
+ styles.top = y + 'px';
+ styles.left = x + 'px';
+ }
+}
- this.options.internal.oldScrollPosition = newPage;
+var HeaderController = function () {
+ function HeaderController() {
+ _classCallCheck(this, HeaderController);
+ }
- if (newPage < oldScrollPosition) {
- newPage = Math.floor(newPage);
- } else if (newPage > oldScrollPosition) {
- newPage = Math.ceil(newPage);
- } else {
- newPage = curPage;
- }
+ _createClass(HeaderController, [{
+ key: "styles",
+ value: function styles() {
+ return {
+ width: this.options.internal.innerWidth + 'px',
+ height: this.options.headerHeight + 'px'
+ };
+ }
+ }, {
+ key: "innerStyles",
+ value: function innerStyles() {
+ return {
+ width: this.columnWidths.total + 'px'
+ };
+ }
+ }, {
+ key: "onSorted",
+ value: function onSorted(sortedColumn) {
+ if (this.options.sortType === 'single') {
+ var unsortColumn = function unsortColumn(column) {
+ if (column !== sortedColumn) {
+ column.sort = undefined;
+ }
+ };
- if (!isNaN(newPage)) {
- this.options.paging.offset = newPage;
+ this.columns.left.forEach(unsortColumn);
+ this.columns.center.forEach(unsortColumn);
+ this.columns.right.forEach(unsortColumn);
}
+
+ this.onSort({
+ column: sortedColumn
+ });
}
}, {
- key: "calculateDepth",
- value: function calculateDepth(row) {
- var depth = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
+ key: "stylesByGroup",
+ value: function stylesByGroup(group) {
+ var styles = {
+ width: this.columnWidths[group] + 'px'
+ };
- var parentProp = this.treeColumn ? this.treeColumn.relationProp : this.groupColumn.prop;
- var prop = this.treeColumn.prop;
- if (!row[parentProp]) {
- return depth;
- }
- if (row.$$depth) {
- return row.$$depth + depth;
+ if (group === 'center') {
+ TranslateXY(styles, this.options.internal.offsetX * -1, 0);
+ } else if (group === 'right') {
+ var offset = (this.columnWidths.total - this.options.internal.innerWidth) * -1;
+ TranslateXY(styles, offset, 0);
}
- var cachedParent = this.index[row[parentProp]];
- if (cachedParent) {
- depth += 1;
- return this.calculateDepth(cachedParent, depth);
- }
- for (var i = 0, len = this.rows.length; i < len; i++) {
- var parent = this.rows[i];
- if (parent[prop] == row[parentProp]) {
- depth += 1;
- return this.calculateDepth(parent, depth);
- }
- }
- return depth;
+ return styles;
}
}, {
- key: "buildRowsByGroup",
- value: function buildRowsByGroup() {
- this.index = {};
- this.rowsByGroup = {};
+ key: "onCheckboxChanged",
+ value: function onCheckboxChanged() {
+ this.onCheckboxChange();
+ }
+ }, {
+ key: "onResized",
+ value: function onResized(column, width) {
+ this.onResize({
+ column: column,
+ width: width
+ });
+ }
+ }]);
- var parentProp = this.treeColumn ? this.treeColumn.relationProp : this.groupColumn.prop;
+ return HeaderController;
+}();
- for (var i = 0, len = this.rows.length; i < len; i++) {
- var row = this.rows[i];
+function HeaderDirective($timeout) {
+ return {
+ restrict: 'E',
+ controller: HeaderController,
+ controllerAs: 'header',
+ scope: true,
+ bindToController: {
+ options: '=',
+ columns: '=',
+ columnWidths: '=',
+ onSort: '&',
+ onResize: '&',
+ onCheckboxChange: '&'
+ },
+ template: "\n ",
+ replace: true,
+ link: function link($scope, $elm, $attrs, ctrl) {
- var relVal = row[parentProp];
- if (relVal) {
- if (this.rowsByGroup[relVal]) {
- this.rowsByGroup[relVal].push(row);
- } else {
- this.rowsByGroup[relVal] = [row];
+ $scope.columnsResorted = function (event, columnId) {
+ var col = findColumnById(columnId),
+ parent = _angular2.default.element(event.currentTarget),
+ newIdx = -1;
+
+ _angular2.default.forEach(parent.children(), function (c, i) {
+ if (columnId === _angular2.default.element(c).attr('data-id')) {
+ newIdx = i;
}
- }
+ });
- if (this.treeColumn) {
- var prop = this.treeColumn.prop;
- this.index[row[prop]] = row;
+ $timeout(function () {
+ _angular2.default.forEach(ctrl.columns, function (group) {
+ var idx = group.indexOf(col);
+ if (idx > -1) {
+ var curColAtIdx = group[newIdx],
+ siblingIdx = ctrl.options.columns.indexOf(curColAtIdx),
+ curIdx = ctrl.options.columns.indexOf(col);
- if (row[parentProp] === undefined) {
- row.$$depth = 0;
- } else {
- var parent = this.index[row[parentProp]];
- if (parent === undefined) {
- for (var j = 0; j < len; j++) {
- if (this.rows[j][prop] == relVal) {
- parent = this.rows[j];
- break;
- }
- }
- }
- if (parent.$$depth === undefined) {
- parent.$$depth = this.calculateDepth(parent);
- }
- row.$$depth = parent.$$depth + 1;
- if (parent.$$children) {
- parent.$$children.push(row[prop]);
- } else {
- parent.$$children = [row[prop]];
- }
- }
- }
- }
- }
- }, {
- key: "buildGroups",
- value: function buildGroups() {
- var _this4 = this;
+ ctrl.options.columns.splice(curIdx, 1);
+ ctrl.options.columns.splice(siblingIdx, 0, col);
- var temp = [];
+ return false;
+ }
+ });
+ });
+ };
- angular.forEach(this.rowsByGroup, function (v, k) {
- temp.push({
- name: k,
- group: true
+ var findColumnById = function findColumnById(columnId) {
+ var columns = ctrl.columns.left.concat(ctrl.columns.center).concat(ctrl.columns.right);
+ return columns.find(function (c) {
+ return c.$id === columnId;
});
+ };
+ }
+ };
+}
- if (_this4.expanded[k]) {
- temp.push.apply(temp, _toConsumableArray(v));
- }
- });
+var HeaderCellController = function () {
+ function HeaderCellController() {
+ _classCallCheck(this, HeaderCellController);
+ }
- return temp;
+ _createClass(HeaderCellController, [{
+ key: "styles",
+ value: function styles() {
+ return {
+ width: this.column.width + 'px',
+ minWidth: this.column.minWidth + 'px',
+ maxWidth: this.column.maxWidth + 'px',
+ height: this.column.height + 'px'
+ };
}
}, {
- key: "isSelected",
- value: function isSelected(row) {
- var selected = false;
+ key: "cellClass",
+ value: function cellClass() {
+ var cls = {
+ 'sortable': this.column.sortable,
+ 'resizable': this.column.resizable
+ };
- if (this.options.selectable) {
- if (this.options.multiSelect) {
- selected = this.selected.indexOf(row) > -1;
- } else {
- selected = this.selected === row;
- }
+ if (this.column.headerClassName) {
+ cls[this.column.headerClassName] = true;
}
- return selected;
+ return cls;
}
}, {
- key: "buildTree",
- value: function buildTree() {
- var temp = [],
- self = this;
+ key: "onSorted",
+ value: function onSorted() {
+ if (this.column.sortable) {
+ this.column.sort = NextSortDirection(this.sortType, this.column.sort);
- function addChildren(fromArray, toArray, level) {
- fromArray.forEach(function (row) {
- var relVal = row[self.treeColumn.relationProp],
- key = row[self.treeColumn.prop],
- groupRows = self.rowsByGroup[key],
- expanded = self.expanded[key];
+ if (this.column.sort === undefined) {
+ this.column.sortPriority = undefined;
+ }
- if (level > 0 || !relVal) {
- toArray.push(row);
- if (groupRows && groupRows.length > 0 && expanded) {
- addChildren(groupRows, toArray, level + 1);
- }
- }
+ this.onSort({
+ column: this.column
});
}
-
- addChildren(this.rows, temp, 0);
-
- return temp;
}
}, {
- key: "getRows",
- value: function getRows(refresh) {
- if ((this.treeColumn || this.groupColumn) && !this.rowsByGroup) {
- return false;
- }
+ key: "sortClass",
+ value: function sortClass() {
+ return {
+ 'sort-btn': true,
+ 'sort-asc icon-down': this.column.sort === 'asc',
+ 'sort-desc icon-up': this.column.sort === 'desc'
+ };
+ }
+ }, {
+ key: "onResized",
+ value: function onResized(width, column) {
+ this.onResize({
+ column: column,
+ width: width
+ });
+ }
+ }, {
+ key: "onCheckboxChange",
+ value: function onCheckboxChange() {
+ this.onCheckboxChanged();
+ }
+ }]);
- var temp;
+ return HeaderCellController;
+}();
- if (this.treeColumn) {
- temp = this.treeTemp || [];
+function HeaderCellDirective($compile) {
+ return {
+ restrict: 'E',
+ controller: HeaderCellController,
+ controllerAs: 'hcell',
+ scope: true,
+ bindToController: {
+ options: '=',
+ column: '=',
+ onCheckboxChange: '&',
+ onSort: '&',
+ sortType: '=',
+ onResize: '&',
+ selected: '='
+ },
+ replace: true,
+ template: "",
+ compile: function compile() {
+ return {
+ pre: function pre($scope, $elm, $attrs, ctrl) {
+ var label = $elm[0].querySelector('.dt-header-cell-label'),
+ cellScope = void 0;
- if (refresh || !this.treeTemp) {
- this.treeTemp = temp = this.buildTree();
- this.count = temp.length;
+ if (ctrl.column.headerTemplate || ctrl.column.headerRenderer) {
+ cellScope = ctrl.options.$outer.$new(false);
- this.tempRows.splice(0, this.tempRows.length);
- }
- } else if (this.groupColumn) {
- temp = this.groupsTemp || [];
+ cellScope.$header = ctrl.column.name;
+ cellScope.$index = $scope.$index;
+ }
- if (refresh || !this.groupsTemp) {
- this.groupsTemp = temp = this.buildGroups();
- this.count = temp.length;
- }
- } else {
- temp = this.rows;
- if (refresh === true) {
- this.tempRows.splice(0, this.tempRows.length);
+ if (ctrl.column.headerTemplate) {
+ var elm = _angular2.default.element("" + ctrl.column.headerTemplate.trim() + " ");
+ _angular2.default.element(label).append($compile(elm)(cellScope));
+ } else if (ctrl.column.headerRenderer) {
+ var _elm = _angular2.default.element(ctrl.column.headerRenderer($elm));
+ _angular2.default.element(label).append($compile(_elm)(cellScope)[0]);
+ } else {
+ var val = ctrl.column.name;
+ if (val === undefined || val === null) val = '';
+ label.textContent = val;
+ }
}
- }
+ };
+ }
+ };
+}
- var idx = 0,
- indexes = this.getFirstLastIndexes(),
- rowIndex = indexes.first;
+var BodyController = function () {
+ function BodyController($scope, $timeout) {
+ var _this4 = this;
- this.tempRows.splice(0, indexes.last - indexes.first);
+ _classCallCheck(this, BodyController);
- while (rowIndex < indexes.last && rowIndex < this.count) {
- var row = temp[rowIndex];
- if (row) {
- row.$$index = rowIndex;
- this.tempRows[idx] = row;
- }
- idx++;
- rowIndex++;
- }
+ this.$scope = $scope;
+ this.tempRows = [];
- this.options.internal.styleTranslator.update(this.tempRows);
+ this.treeColumn = this.options.columns.find(function (c) {
+ return c.isTreeColumn;
+ });
- return this.tempRows;
- }
- }, {
- key: "styles",
- value: function styles() {
- var styles = {
- width: this.options.internal.innerWidth + 'px'
- };
+ this.groupColumn = this.options.columns.find(function (c) {
+ return c.group;
+ });
- if (!this.options.scrollbarV) {
- styles.overflowY = 'hidden';
- } else if (this.options.scrollbarH === false) {
- styles.overflowX = 'hidden';
- }
+ $scope.$watchCollection('body.rows', this.rowsUpdated.bind(this));
- if (this.options.scrollbarV) {
- styles.height = this.options.internal.bodyHeight + 'px';
- }
+ if (this.options.scrollbarV || !this.options.scrollbarV && this.options.paging.externalPaging) {
+ var sized = false;
+ $scope.$watch('body.options.paging.size', function (newVal, oldVal) {
+ if (!sized || newVal > oldVal) {
+ _this4.getRows();
+ sized = true;
+ }
+ });
- return styles;
+ $scope.$watch('body.options.paging.count', function (count) {
+ _this4.count = count;
+ _this4.updatePage();
+ });
+
+ $scope.$watch('body.options.paging.offset', function (newVal) {
+ if (_this4.options.paging.size) {
+ _this4.onPage({
+ offset: newVal,
+ size: _this4.options.paging.size
+ });
+ }
+ });
}
- }, {
- key: "rowStyles",
- value: function rowStyles(row) {
- var styles = {};
+ }
- if (this.options.rowHeight === 'auto') {
- styles.height = this.options.rowHeight + 'px';
- }
+ _createClass(BodyController, [{
+ key: "rowsUpdated",
+ value: function rowsUpdated(newVal, oldVal) {
+ if (newVal) {
+ if (!this.options.paging.externalPaging) {
+ this.options.paging.count = newVal.length;
+ }
- return styles;
- }
- }, {
- key: "groupRowStyles",
- value: function groupRowStyles(row) {
- var styles = this.rowStyles(row);
- styles.width = this.columnWidths.total + 'px';
- return styles;
- }
- }, {
- key: "rowClasses",
- value: function rowClasses(row) {
- var styles = {
- 'selected': this.isSelected(row),
- 'dt-row-even': row && row.$$index % 2 === 0,
- 'dt-row-odd': row && row.$$index % 2 !== 0
- };
+ this.count = this.options.paging.count;
- if (this.treeColumn) {
- styles['dt-leaf'] = this.rowsByGroup[row[this.treeColumn.relationProp]];
+ if (this.treeColumn || this.groupColumn) {
+ this.buildRowsByGroup();
+ }
- styles['dt-has-leafs'] = this.rowsByGroup[row[this.treeColumn.prop]];
+ if (this.options.scrollbarV) {
+ var refresh = newVal && oldVal && (newVal.length === oldVal.length || newVal.length < oldVal.length);
- styles['dt-depth-' + row.$$depth] = true;
- }
+ this.getRows(refresh);
+ } else {
+ var rows = this.rows;
- return styles;
- }
- }, {
- key: "getRowValue",
- value: function getRowValue(idx) {
- return this.tempRows[idx];
- }
- }, {
- key: "getRowExpanded",
- value: function getRowExpanded(row) {
- if (this.treeColumn) {
- return this.expanded[row[this.treeColumn.prop]];
- } else if (this.groupColumn) {
- return this.expanded[row.name];
- }
- }
- }, {
- key: "getRowHasChildren",
- value: function getRowHasChildren(row) {
- if (!this.treeColumn) return;
- var children = this.rowsByGroup[row[this.treeColumn.prop]];
- return children !== undefined || children && !children.length;
- }
- }, {
- key: "onTreeToggled",
- value: function onTreeToggled(row, cell) {
- var val = row[this.treeColumn.prop];
- this.expanded[val] = !this.expanded[val];
+ if (this.treeColumn) {
+ rows = this.buildTree();
+ } else if (this.groupColumn) {
+ rows = this.buildGroups();
+ }
- if (this.options.scrollbarV) {
- this.getRows(true);
- } else {
- var _tempRows2;
+ if (this.options.paging.externalPaging) {
+ var idxs = this.getFirstLastIndexes(),
+ idx = idxs.first;
- var values = this.buildTree();
- this.tempRows.splice(0, this.tempRows.length);
- (_tempRows2 = this.tempRows).push.apply(_tempRows2, _toConsumableArray(values));
- }
+ this.tempRows.splice(0, this.tempRows.length);
+ while (idx < idxs.last) {
+ this.tempRows.push(rows[idx++]);
+ }
+ } else {
+ var _tempRows;
- this.onTreeToggle({
- row: row,
- cell: cell
- });
+ this.tempRows.splice(0, this.tempRows.length);
+ (_tempRows = this.tempRows).push.apply(_tempRows, _toConsumableArray(rows));
+ }
+ }
+ }
}
}, {
- key: "onGroupToggle",
- value: function onGroupToggle(row) {
- this.expanded[row.name] = !this.expanded[row.name];
+ key: "getFirstLastIndexes",
+ value: function getFirstLastIndexes() {
+ var firstRowIndex, endIndex;
if (this.options.scrollbarV) {
- this.getRows(true);
+ firstRowIndex = Math.max(Math.floor((this.options.internal.offsetY || 0) / this.options.rowHeight, 0), 0);
+ endIndex = Math.min(firstRowIndex + this.options.paging.size, this.count);
} else {
- var _tempRows3;
-
- var values = this.buildGroups();
- this.tempRows.splice(0, this.tempRows.length);
- (_tempRows3 = this.tempRows).push.apply(_tempRows3, _toConsumableArray(values));
+ if (this.options.paging.externalPaging) {
+ firstRowIndex = Math.max(this.options.paging.offset * this.options.paging.size, 0);
+ endIndex = Math.min(firstRowIndex + this.options.paging.size, this.count);
+ } else {
+ endIndex = this.count;
+ }
}
- }
- }]);
-
- return BodyController;
-}();
-
-function BodyDirective($timeout) {
- return {
- restrict: 'E',
- controller: BodyController,
- controllerAs: 'body',
- bindToController: {
- columns: '=',
- columnWidths: '=',
- rows: '=',
- options: '=',
- selected: '=?',
- expanded: '=?',
- onPage: '&',
- onTreeToggle: '&',
- onSelect: '&',
- onRowClick: '&',
- onRowDblClick: '&'
- },
- scope: true,
- template: "\n \n \n
\n \n \n \n \n \n
\n
\n
\n
\n
"
- };
-}
-function NextSortDirection(sortType, currentSort) {
- if (sortType === 'single') {
- if (currentSort === 'asc') {
- return 'desc';
- } else {
- return 'asc';
- }
- } else {
- if (!currentSort) {
- return 'asc';
- } else if (currentSort === 'asc') {
- return 'desc';
- } else if (currentSort === 'desc') {
- return undefined;
- }
- }
-}
-
-var HeaderCellController = function () {
- function HeaderCellController() {
- _classCallCheck(this, HeaderCellController);
- }
-
- _createClass(HeaderCellController, [{
- key: "styles",
- value: function styles() {
return {
- width: this.column.width + 'px',
- minWidth: this.column.minWidth + 'px',
- maxWidth: this.column.maxWidth + 'px',
- height: this.column.height + 'px'
+ first: firstRowIndex,
+ last: endIndex
};
}
}, {
- key: "cellClass",
- value: function cellClass() {
- var cls = {
- 'sortable': this.column.sortable,
- 'resizable': this.column.resizable
- };
+ key: "updatePage",
+ value: function updatePage() {
+ var curPage = this.options.paging.offset,
+ idxs = this.getFirstLastIndexes();
- if (this.column.headerClassName) {
- cls[this.column.headerClassName] = true;
+ if (this.options.internal.oldScrollPosition === undefined) {
+ this.options.internal.oldScrollPosition = 0;
}
- return cls;
- }
- }, {
- key: "onSorted",
- value: function onSorted() {
- if (this.column.sortable) {
- this.column.sort = NextSortDirection(this.sortType, this.column.sort);
+ var oldScrollPosition = this.options.internal.oldScrollPosition,
+ newPage = idxs.first / this.options.paging.size;
- if (this.column.sort === undefined) {
- this.column.sortPriority = undefined;
- }
+ this.options.internal.oldScrollPosition = newPage;
- this.onSort({
- column: this.column
- });
- }
- }
- }, {
- key: "sortClass",
- value: function sortClass() {
- return {
- 'sort-btn': true,
- 'sort-asc icon-down': this.column.sort === 'asc',
- 'sort-desc icon-up': this.column.sort === 'desc'
- };
- }
- }, {
- key: "onResized",
- value: function onResized(width, column) {
- this.onResize({
- column: column,
- width: width
- });
+ if (newPage < oldScrollPosition) {
+ newPage = Math.floor(newPage);
+ } else if (newPage > oldScrollPosition) {
+ newPage = Math.ceil(newPage);
+ } else {
+ newPage = curPage;
+ }
+
+ if (!isNaN(newPage)) {
+ this.options.paging.offset = newPage;
+ }
}
}, {
- key: "onCheckboxChange",
- value: function onCheckboxChange() {
- this.onCheckboxChanged();
- }
- }]);
+ key: "calculateDepth",
+ value: function calculateDepth(row) {
+ var depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
- return HeaderCellController;
-}();
+ var parentProp = this.treeColumn ? this.treeColumn.relationProp : this.groupColumn.prop;
+ var prop = this.treeColumn.prop;
+ if (!row[parentProp]) {
+ return depth;
+ }
+ if (row.$$depth) {
+ return row.$$depth + depth;
+ }
-function HeaderCellDirective($compile) {
- return {
- restrict: 'E',
- controller: HeaderCellController,
- controllerAs: 'hcell',
- scope: true,
- bindToController: {
- options: '=',
- column: '=',
- onCheckboxChange: '&',
- onSort: '&',
- sortType: '=',
- onResize: '&',
- selected: '='
- },
- replace: true,
- template: "",
- compile: function compile() {
- return {
- pre: function pre($scope, $elm, $attrs, ctrl) {
- var label = $elm[0].querySelector('.dt-header-cell-label'),
- cellScope = void 0;
+ var cachedParent = this.index[row[parentProp]];
+ if (cachedParent) {
+ depth += 1;
+ return this.calculateDepth(cachedParent, depth);
+ }
+ for (var i = 0, len = this.rows.length; i < len; i++) {
+ var parent = this.rows[i];
+ if (parent[prop] == row[parentProp]) {
+ depth += 1;
+ return this.calculateDepth(parent, depth);
+ }
+ }
+ return depth;
+ }
+ }, {
+ key: "buildRowsByGroup",
+ value: function buildRowsByGroup() {
+ this.index = {};
+ this.rowsByGroup = {};
- if (ctrl.column.headerTemplate || ctrl.column.headerRenderer) {
- cellScope = ctrl.options.$outer.$new(false);
+ var parentProp = this.treeColumn ? this.treeColumn.relationProp : this.groupColumn.prop;
- cellScope.$header = ctrl.column.name;
- cellScope.$index = $scope.$index;
- }
+ for (var i = 0, len = this.rows.length; i < len; i++) {
+ var row = this.rows[i];
- if (ctrl.column.headerTemplate) {
- var elm = angular.element("" + ctrl.column.headerTemplate.trim() + " ");
- angular.element(label).append($compile(elm)(cellScope));
- } else if (ctrl.column.headerRenderer) {
- var _elm = angular.element(ctrl.column.headerRenderer($elm));
- angular.element(label).append($compile(_elm)(cellScope)[0]);
+ var relVal = row[parentProp];
+ if (relVal) {
+ if (this.rowsByGroup[relVal]) {
+ this.rowsByGroup[relVal].push(row);
} else {
- var val = ctrl.column.name;
- if (val === undefined || val === null) val = '';
- label.textContent = val;
+ this.rowsByGroup[relVal] = [row];
}
}
- };
- }
- };
-}
-var HeaderController = function () {
- function HeaderController() {
- _classCallCheck(this, HeaderController);
- }
+ if (this.treeColumn) {
+ var prop = this.treeColumn.prop;
+ this.index[row[prop]] = row;
- _createClass(HeaderController, [{
- key: "styles",
- value: function styles() {
- return {
- width: this.options.internal.innerWidth + 'px',
- height: this.options.headerHeight + 'px'
- };
- }
- }, {
- key: "innerStyles",
- value: function innerStyles() {
- return {
- width: this.columnWidths.total + 'px'
- };
+ if (row[parentProp] === undefined) {
+ row.$$depth = 0;
+ } else {
+ var parent = this.index[row[parentProp]];
+ if (parent === undefined) {
+ for (var j = 0; j < len; j++) {
+ if (this.rows[j][prop] == relVal) {
+ parent = this.rows[j];
+ break;
+ }
+ }
+ }
+ if (parent.$$depth === undefined) {
+ parent.$$depth = this.calculateDepth(parent);
+ }
+ row.$$depth = parent.$$depth + 1;
+ if (parent.$$children) {
+ parent.$$children.push(row[prop]);
+ } else {
+ parent.$$children = [row[prop]];
+ }
+ }
+ }
+ }
}
}, {
- key: "onSorted",
- value: function onSorted(sortedColumn) {
- if (this.options.sortType === 'single') {
- var unsortColumn = function unsortColumn(column) {
- if (column !== sortedColumn) {
- column.sort = undefined;
- }
- };
+ key: "buildGroups",
+ value: function buildGroups() {
+ var _this5 = this;
- this.columns.left.forEach(unsortColumn);
- this.columns.center.forEach(unsortColumn);
- this.columns.right.forEach(unsortColumn);
- }
+ var temp = [];
- this.onSort({
- column: sortedColumn
+ _angular2.default.forEach(this.rowsByGroup, function (v, k) {
+ temp.push({
+ name: k,
+ group: true
+ });
+
+ if (_this5.expanded[k]) {
+ temp.push.apply(temp, _toConsumableArray(v));
+ }
});
+
+ return temp;
}
}, {
- key: "stylesByGroup",
- value: function stylesByGroup(group) {
- var styles = {
- width: this.columnWidths[group] + 'px'
- };
+ key: "isSelected",
+ value: function isSelected(row) {
+ var selected = false;
- if (group === 'center') {
- TranslateXY(styles, this.options.internal.offsetX * -1, 0);
- } else if (group === 'right') {
- var offset = (this.columnWidths.total - this.options.internal.innerWidth) * -1;
- TranslateXY(styles, offset, 0);
+ if (this.options.selectable) {
+ if (this.options.multiSelect) {
+ selected = this.selected.indexOf(row) > -1;
+ } else {
+ selected = this.selected === row;
+ }
}
- return styles;
- }
- }, {
- key: "onCheckboxChanged",
- value: function onCheckboxChanged() {
- this.onCheckboxChange();
+ return selected;
}
}, {
- key: "onResized",
- value: function onResized(column, width) {
- this.onResize({
- column: column,
- width: width
- });
- }
- }]);
-
- return HeaderController;
-}();
-
-function HeaderDirective($timeout) {
- return {
- restrict: 'E',
- controller: HeaderController,
- controllerAs: 'header',
- scope: true,
- bindToController: {
- options: '=',
- columns: '=',
- columnWidths: '=',
- onSort: '&',
- onResize: '&',
- onCheckboxChange: '&'
- },
- template: "\n ",
- replace: true,
- link: function link($scope, $elm, $attrs, ctrl) {
+ key: "buildTree",
+ value: function buildTree() {
+ var temp = [],
+ self = this;
- $scope.columnsResorted = function (event, columnId) {
- var col = findColumnById(columnId),
- parent = angular.element(event.currentTarget),
- newIdx = -1;
+ function addChildren(fromArray, toArray, level) {
+ fromArray.forEach(function (row) {
+ var relVal = row[self.treeColumn.relationProp],
+ key = row[self.treeColumn.prop],
+ groupRows = self.rowsByGroup[key],
+ expanded = self.expanded[key];
- angular.forEach(parent.children(), function (c, i) {
- if (columnId === angular.element(c).attr('data-id')) {
- newIdx = i;
+ if (level > 0 || !relVal) {
+ toArray.push(row);
+ if (groupRows && groupRows.length > 0 && expanded) {
+ addChildren(groupRows, toArray, level + 1);
+ }
}
});
+ }
- $timeout(function () {
- angular.forEach(ctrl.columns, function (group) {
- var idx = group.indexOf(col);
- if (idx > -1) {
- var curColAtIdx = group[newIdx],
- siblingIdx = ctrl.options.columns.indexOf(curColAtIdx),
- curIdx = ctrl.options.columns.indexOf(col);
-
- ctrl.options.columns.splice(curIdx, 1);
- ctrl.options.columns.splice(siblingIdx, 0, col);
-
- return false;
- }
- });
- });
- };
+ addChildren(this.rows, temp, 0);
- var findColumnById = function findColumnById(columnId) {
- var columns = ctrl.columns.left.concat(ctrl.columns.center).concat(ctrl.columns.right);
- return columns.find(function (c) {
- return c.$id === columnId;
- });
- };
+ return temp;
}
- };
-}
-
-function SortableDirective($timeout) {
- return {
- restrict: 'A',
- scope: {
- isSortable: '=sortable',
- onSortableSort: '&'
- },
- link: function link($scope, $element, $attrs) {
- var rootEl = $element[0],
- dragEl,
- nextEl,
- dropEl;
-
- function isbefore(a, b) {
- if (a.parentNode == b.parentNode) {
- for (var cur = a; cur; cur = cur.previousSibling) {
- if (cur === b) {
- return true;
- }
- }
- }
+ }, {
+ key: "getRows",
+ value: function getRows(refresh) {
+ if ((this.treeColumn || this.groupColumn) && !this.rowsByGroup) {
return false;
- };
-
- function onDragEnter(e) {
- var target = e.target;
- if (isbefore(dragEl, target)) {
- target.parentNode.insertBefore(dragEl, target);
- } else if (target.nextSibling && target.hasAttribute('draggable')) {
- target.parentNode.insertBefore(dragEl, target.nextSibling.nextSibling);
- }
- };
+ }
- function onDragEnd(evt) {
- evt.preventDefault();
+ var temp;
- dragEl.classList.remove('dt-clone');
+ if (this.treeColumn) {
+ temp = this.treeTemp || [];
- $element.off('dragend', onDragEnd);
- $element.off('dragenter', onDragEnter);
+ if (refresh || !this.treeTemp) {
+ this.treeTemp = temp = this.buildTree();
+ this.count = temp.length;
- if (nextEl !== dragEl.nextSibling) {
- $scope.onSortableSort({
- event: evt,
- columnId: angular.element(dragEl).attr('data-id')
- });
+ this.tempRows.splice(0, this.tempRows.length);
}
- };
+ } else if (this.groupColumn) {
+ temp = this.groupsTemp || [];
- function onDragStart(evt) {
- if (!$scope.isSortable) return false;
- evt = evt.originalEvent || evt;
+ if (refresh || !this.groupsTemp) {
+ this.groupsTemp = temp = this.buildGroups();
+ this.count = temp.length;
+ }
+ } else {
+ temp = this.rows;
+ if (refresh === true) {
+ this.tempRows.splice(0, this.tempRows.length);
+ }
+ }
- dragEl = evt.target;
- nextEl = dragEl.nextSibling;
- dragEl.classList.add('dt-clone');
+ var idx = 0,
+ indexes = this.getFirstLastIndexes(),
+ rowIndex = indexes.first;
- evt.dataTransfer.effectAllowed = 'move';
- evt.dataTransfer.setData('Text', dragEl.textContent);
+ this.tempRows.splice(0, indexes.last - indexes.first);
- $element.on('dragenter', onDragEnter);
- $element.on('dragend', onDragEnd);
- };
+ while (rowIndex < indexes.last && rowIndex < this.count) {
+ var row = temp[rowIndex];
+ if (row) {
+ row.$$index = rowIndex;
+ this.tempRows[idx] = row;
+ }
+ idx++;
+ rowIndex++;
+ }
- $element.on('dragstart', onDragStart);
+ this.options.internal.styleTranslator.update(this.tempRows);
- $scope.$on('$destroy', function () {
- $element.off('dragstart', onDragStart);
- });
+ return this.tempRows;
}
- };
-}
+ }, {
+ key: "styles",
+ value: function styles() {
+ var styles = {
+ width: this.options.internal.innerWidth + 'px'
+ };
-function ResizableDirective($document, $timeout) {
- return {
- restrict: 'A',
- scope: {
- isResizable: '=resizable',
- minWidth: '=',
- maxWidth: '=',
- onResize: '&'
- },
- link: function link($scope, $element, $attrs) {
- if ($scope.isResizable) {
- $element.addClass('resizable');
+ if (!this.options.scrollbarV) {
+ styles.overflowY = 'hidden';
+ } else if (this.options.scrollbarH === false) {
+ styles.overflowX = 'hidden';
}
- var handle = angular.element(" "),
- parent = $element.parent(),
- prevScreenX;
+ if (this.options.scrollbarV) {
+ styles.height = this.options.internal.bodyHeight + 'px';
+ }
- handle.on('mousedown', function (event) {
- if (!$element[0].classList.contains('resizable')) {
- return false;
- }
+ return styles;
+ }
+ }, {
+ key: "rowStyles",
+ value: function rowStyles(row) {
+ var styles = {};
- event.stopPropagation();
- event.preventDefault();
+ if (this.options.rowHeight === 'auto') {
+ styles.height = this.options.rowHeight + 'px';
+ }
- $document.on('mousemove', mousemove);
- $document.on('mouseup', mouseup);
- });
+ return styles;
+ }
+ }, {
+ key: "groupRowStyles",
+ value: function groupRowStyles(row) {
+ var styles = this.rowStyles(row);
+ styles.width = this.columnWidths.total + 'px';
+ return styles;
+ }
+ }, {
+ key: "rowClasses",
+ value: function rowClasses(row) {
+ var styles = {
+ 'selected': this.isSelected(row),
+ 'dt-row-even': row && row.$$index % 2 === 0,
+ 'dt-row-odd': row && row.$$index % 2 !== 0
+ };
- function mousemove(event) {
- event = event.originalEvent || event;
+ if (this.treeColumn) {
+ styles['dt-leaf'] = this.rowsByGroup[row[this.treeColumn.relationProp]];
- var width = parent[0].clientWidth,
- movementX = event.movementX || event.mozMovementX || event.screenX - prevScreenX,
- newWidth = width + (movementX || 0);
+ styles['dt-has-leafs'] = this.rowsByGroup[row[this.treeColumn.prop]];
- prevScreenX = event.screenX;
+ styles['dt-depth-' + row.$$depth] = true;
+ }
- if ((!$scope.minWidth || newWidth >= $scope.minWidth) && (!$scope.maxWidth || newWidth <= $scope.maxWidth)) {
- parent.css({
- width: newWidth + 'px'
- });
- }
+ return styles;
+ }
+ }, {
+ key: "getRowValue",
+ value: function getRowValue(idx) {
+ return this.tempRows[idx];
+ }
+ }, {
+ key: "getRowExpanded",
+ value: function getRowExpanded(row) {
+ if (this.treeColumn) {
+ return this.expanded[row[this.treeColumn.prop]];
+ } else if (this.groupColumn) {
+ return this.expanded[row.name];
}
+ }
+ }, {
+ key: "getRowHasChildren",
+ value: function getRowHasChildren(row) {
+ if (!this.treeColumn) return;
+ var children = this.rowsByGroup[row[this.treeColumn.prop]];
+ return children !== undefined || children && !children.length;
+ }
+ }, {
+ key: "onTreeToggled",
+ value: function onTreeToggled(row, cell) {
+ var val = row[this.treeColumn.prop];
+ this.expanded[val] = !this.expanded[val];
- function mouseup() {
- if ($scope.onResize) {
- $timeout(function () {
- var width = parent[0].clientWidth;
- if (width < $scope.minWidth) {
- width = $scope.minWidth;
- }
- $scope.onResize({ width: width });
- });
- }
+ if (this.options.scrollbarV) {
+ this.getRows(true);
+ } else {
+ var _tempRows2;
- $document.unbind('mousemove', mousemove);
- $document.unbind('mouseup', mouseup);
+ var values = this.buildTree();
+ this.tempRows.splice(0, this.tempRows.length);
+ (_tempRows2 = this.tempRows).push.apply(_tempRows2, _toConsumableArray(values));
}
- $element.append(handle);
+ this.onTreeToggle({
+ row: row,
+ cell: cell
+ });
}
- };
-}
+ }, {
+ key: "onGroupToggle",
+ value: function onGroupToggle(row) {
+ this.expanded[row.name] = !this.expanded[row.name];
-function throttle(func, wait, options) {
- var context, args, result;
- var timeout = null;
- var previous = 0;
- options || (options = {});
- var later = function later() {
- previous = options.leading === false ? 0 : new Date();
- timeout = null;
- result = func.apply(context, args);
- };
- return function () {
- var now = new Date();
- if (!previous && options.leading === false) previous = now;
- var remaining = wait - (now - previous);
- context = this;
- args = arguments;
- if (remaining <= 0) {
- clearTimeout(timeout);
- timeout = null;
- previous = now;
- result = func.apply(context, args);
- } else if (!timeout && options.trailing !== false) {
- timeout = setTimeout(later, remaining);
- }
- return result;
- };
-}
-
-function ScrollbarWidth() {
- var outer = document.createElement("div");
- outer.style.visibility = "hidden";
- outer.style.width = "100px";
- outer.style.msOverflowStyle = "scrollbar";
- document.body.appendChild(outer);
-
- var widthNoScroll = outer.offsetWidth;
- outer.style.overflow = "scroll";
+ if (this.options.scrollbarV) {
+ this.getRows(true);
+ } else {
+ var _tempRows3;
- var inner = document.createElement("div");
- inner.style.width = "100%";
- outer.appendChild(inner);
+ var values = this.buildGroups();
+ this.tempRows.splice(0, this.tempRows.length);
+ (_tempRows3 = this.tempRows).push.apply(_tempRows3, _toConsumableArray(values));
+ }
+ }
+ }]);
- var widthWithScroll = inner.offsetWidth;
- outer.parentNode.removeChild(outer);
+ return BodyController;
+}();
- return widthNoScroll - widthWithScroll;
+function BodyDirective($timeout) {
+ return {
+ restrict: 'E',
+ controller: BodyController,
+ controllerAs: 'body',
+ bindToController: {
+ columns: '=',
+ columnWidths: '=',
+ rows: '=',
+ options: '=',
+ selected: '=?',
+ expanded: '=?',
+ onPage: '&',
+ onTreeToggle: '&',
+ onSelect: '&',
+ onRowClick: '&',
+ onRowDblClick: '&'
+ },
+ scope: true,
+ template: "\n \n \n
\n \n \n \n \n \n
\n
\n
\n
\n
"
+ };
}
-var DataTableService = {
- columns: {},
- dTables: {},
+var StyleTranslator = function () {
+ function StyleTranslator(height) {
+ _classCallCheck(this, StyleTranslator);
- saveColumns: function saveColumns(id, columnElms) {
- if (columnElms && columnElms.length) {
- var columnsArray = [].slice.call(columnElms);
- this.dTables[id] = columnsArray;
- }
- },
- buildColumns: function buildColumns(scope, parse) {
- var _this5 = this;
+ this.height = height;
+ this.map = new Map();
+ }
- angular.forEach(this.dTables, function (columnElms, id) {
- _this5.columns[id] = [];
+ _createClass(StyleTranslator, [{
+ key: "update",
+ value: function update(rows) {
+ var n = 0;
+ while (n <= this.map.size) {
+ var dom = this.map.get(n);
+ var model = rows[n];
+ if (dom && model) {
+ TranslateXY(dom[0].style, 0, model.$$index * this.height);
+ }
+ n++;
+ }
+ }
+ }, {
+ key: "register",
+ value: function register(idx, dom) {
+ this.map.set(idx, dom);
+ }
+ }]);
- angular.forEach(columnElms, function (c) {
- var column = {};
+ return StyleTranslator;
+}();
- var visible = true;
+function ScrollerDirective($timeout, $rootScope) {
+ return {
+ restrict: 'E',
+ require: '^dtBody',
+ transclude: true,
+ replace: true,
+ template: "
",
+ link: function link($scope, $elm, $attrs, ctrl) {
+ var ticking = false,
+ lastScrollY = 0,
+ lastScrollX = 0,
+ parent = $elm.parent();
- angular.forEach(c.attributes, function (attr) {
- var attrName = CamelCase(attr.name);
+ ctrl.options.internal.styleTranslator = new StyleTranslator(ctrl.options.rowHeight);
- switch (attrName) {
- case 'class':
- column.className = attr.value;
- break;
- case 'name':
- case 'prop':
- column[attrName] = attr.value;
- break;
- case 'headerRenderer':
- case 'cellRenderer':
- case 'cellDataGetter':
- column[attrName] = parse(attr.value);
- break;
- case 'visible':
- visible = parse(attr.value)(scope);
- break;
- default:
- column[attrName] = parse(attr.value)(scope);
- break;
- }
- });
+ ctrl.options.internal.setYOffset = function (offsetY) {
+ parent[0].scrollTop = offsetY;
+ };
- var header = c.getElementsByTagName('column-header');
- if (header.length) {
- column.headerTemplate = header[0].innerHTML;
- c.removeChild(header[0]);
- }
+ function update() {
+ ctrl.options.internal.offsetY = lastScrollY;
+ ctrl.options.internal.offsetX = lastScrollX;
+ ctrl.updatePage();
- if (c.innerHTML !== '') {
- column.template = c.innerHTML;
+ if (ctrl.options.scrollbarV) {
+ ctrl.getRows();
}
- if (visible) _this5.columns[id].push(column);
- });
- });
-
- this.dTables = {};
- }
-};
-
-function ObjectId() {
- var timestamp = (new Date().getTime() / 1000 | 0).toString(16);
- return timestamp + 'xxxxxxxxxxxxxxxx'.replace(/[x]/g, function () {
- return (Math.random() * 16 | 0).toString(16);
- }).toLowerCase();
-}
+ ctrl.options.$outer.$digest();
-function ScaleColumns(colsByGroup, maxWidth, totalFlexGrow) {
- angular.forEach(colsByGroup, function (cols) {
- cols.forEach(function (column) {
- if (!column.canAutoResize) {
- maxWidth -= column.width;
- totalFlexGrow -= column.flexGrow;
- } else {
- column.width = 0;
+ ticking = false;
}
- });
- });
- var hasMinWidth = {};
- var remainingWidth = maxWidth;
-
- var _loop = function _loop() {
- var widthPerFlexPoint = remainingWidth / totalFlexGrow;
- remainingWidth = 0;
- angular.forEach(colsByGroup, function (cols) {
- cols.forEach(function (column, i) {
- if (column.canAutoResize && !hasMinWidth[i]) {
- var newWidth = column.width + column.flexGrow * widthPerFlexPoint;
- if (column.minWidth !== undefined && newWidth < column.minWidth) {
- remainingWidth += newWidth - column.minWidth;
- column.width = column.minWidth;
- hasMinWidth[i] = true;
- } else {
- column.width = newWidth;
- }
+ function requestTick() {
+ if (!ticking) {
+ requestAnimFrame(update);
+ ticking = true;
}
- });
- });
- };
+ }
- do {
- _loop();
- } while (remainingWidth !== 0);
-}
+ parent.on('scroll', function (ev) {
+ lastScrollY = this.scrollTop;
+ lastScrollX = this.scrollLeft;
+ requestTick();
+ });
-function ColumnsByPin(cols) {
- var ret = {
- left: [],
- center: [],
- right: []
- };
+ $scope.$on('$destroy', function () {
+ parent.off('scroll');
+ });
- for (var i = 0, len = cols.length; i < len; i++) {
- var c = cols[i];
- if (c.frozenLeft) {
- ret.left.push(c);
- } else if (c.frozenRight) {
- ret.right.push(c);
- } else {
- ret.center.push(c);
+ $scope.scrollerStyles = function () {
+ if (ctrl.options.scrollbarV) {
+ return {
+ height: ctrl.count * ctrl.options.rowHeight + 'px'
+ };
+ }
+ };
}
- }
-
- return ret;
+ };
}
-function GetTotalFlexGrow(columns) {
- var totalFlexGrow = 0;
+var KEYS = {
+ BACKSPACE: 8,
+ TAB: 9,
+ RETURN: 13,
+ ALT: 18,
+ ESC: 27,
+ SPACE: 32,
+ PAGE_UP: 33,
+ PAGE_DOWN: 34,
+ END: 35,
+ HOME: 36,
+ LEFT: 37,
+ UP: 38,
+ RIGHT: 39,
+ DOWN: 40,
+ DELETE: 46,
+ COMMA: 188,
+ PERIOD: 190,
+ A: 65,
+ Z: 90,
+ ZERO: 48,
+ NUMPAD_0: 96,
+ NUMPAD_9: 105
+};
- var _iteratorNormalCompletion = true;
- var _didIteratorError = false;
- var _iteratorError = undefined;
+var SelectionController = function () {
+ function SelectionController($scope) {
+ _classCallCheck(this, SelectionController);
- try {
- for (var _iterator = columns[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
- var c = _step.value;
+ this.body = $scope.body;
+ this.options = $scope.body.options;
+ this.selected = $scope.body.selected;
+ }
- totalFlexGrow += c.flexGrow || 0;
- }
- } catch (err) {
- _didIteratorError = true;
- _iteratorError = err;
- } finally {
- try {
- if (!_iteratorNormalCompletion && _iterator.return) {
- _iterator.return();
+ _createClass(SelectionController, [{
+ key: "keyDown",
+ value: function keyDown(ev, index, row) {
+ if (KEYS[ev.keyCode]) {
+ ev.preventDefault();
}
- } finally {
- if (_didIteratorError) {
- throw _iteratorError;
+
+ if (ev.keyCode === KEYS.DOWN) {
+ var next = ev.target.nextElementSibling;
+ if (next) {
+ next.focus();
+ }
+ } else if (ev.keyCode === KEYS.UP) {
+ var prev = ev.target.previousElementSibling;
+ if (prev) {
+ prev.focus();
+ }
+ } else if (ev.keyCode === KEYS.RETURN) {
+ this.selectRow(index, row);
}
}
- }
-
- return totalFlexGrow;
-}
-
-function ColumnTotalWidth(columns, prop) {
- var totalWidth = 0;
-
- columns.forEach(function (c) {
- var has = prop && c[prop];
- totalWidth = totalWidth + (has ? c[prop] : c.width);
- });
-
- return totalWidth;
-}
-
-function AdjustColumnWidths(allColumns, expectedWidth) {
- var columnsWidth = ColumnTotalWidth(allColumns),
- totalFlexGrow = GetTotalFlexGrow(allColumns),
- colsByGroup = ColumnsByPin(allColumns);
-
- if (columnsWidth !== expectedWidth) {
- ScaleColumns(colsByGroup, expectedWidth, totalFlexGrow);
- }
-}
-
-function ForceFillColumnWidths(allColumns, expectedWidth, startIdx) {
- var contentWidth = 0,
- columnsToResize = startIdx > -1 ? allColumns.slice(startIdx, allColumns.length).filter(function (c) {
- return c.canAutoResize;
- }) : allColumns.filter(function (c) {
- return c.canAutoResize;
- });
+ }, {
+ key: "rowClicked",
+ value: function rowClicked(event, index, row) {
+ if (!this.options.checkboxSelection) {
+ this.selectRow(event, index, row);
+ }
- allColumns.forEach(function (c) {
- if (!c.canAutoResize) {
- contentWidth += c.width;
- } else {
- contentWidth += c.$$oldWidth || c.width;
+ this.body.onRowClick({ row: row });
}
- });
-
- var remainingWidth = expectedWidth - contentWidth,
- additionWidthPerColumn = remainingWidth / columnsToResize.length,
- exceedsWindow = contentWidth > expectedWidth;
-
- columnsToResize.forEach(function (column) {
- if (exceedsWindow) {
- column.width = column.$$oldWidth || column.width;
- } else {
- if (!column.$$oldWidth) {
- column.$$oldWidth = column.width;
+ }, {
+ key: "rowDblClicked",
+ value: function rowDblClicked(event, index, row) {
+ if (!this.options.checkboxSelection) {
+ event.preventDefault();
+ this.selectRow(event, index, row);
}
- var newSize = column.$$oldWidth + additionWidthPerColumn;
- if (column.minWith && newSize < column.minWidth) {
- column.width = column.minWidth;
- } else if (column.maxWidth && newSize > column.maxWidth) {
- column.width = column.maxWidth;
- } else {
- column.width = newSize;
- }
+ this.body.onRowDblClick({ row: row });
}
- });
-}
-
-function ColumnGroupWidths(groups, all) {
- return {
- left: ColumnTotalWidth(groups.left),
- center: ColumnTotalWidth(groups.center),
- right: ColumnTotalWidth(groups.right),
- total: ColumnTotalWidth(all)
- };
-}
-
-var ColumnDefaults = {
- frozenLeft: false,
-
- frozenRight: false,
-
- className: undefined,
-
- headerClassName: undefined,
-
- flexGrow: 0,
+ }, {
+ key: "onCheckboxChange",
+ value: function onCheckboxChange(event, index, row) {
+ this.selectRow(event, index, row);
+ }
+ }, {
+ key: "selectRow",
+ value: function selectRow(event, index, row) {
+ if (this.options.selectable) {
+ if (this.options.multiSelect) {
+ var isCtrlKeyDown = event.ctrlKey || event.metaKey,
+ isShiftKeyDown = event.shiftKey;
- minWidth: 100,
+ if (isShiftKeyDown) {
+ this.selectRowsBetween(index, row);
+ } else {
+ var idx = this.selected.indexOf(row);
+ if (idx > -1) {
+ this.selected.splice(idx, 1);
+ } else {
+ if (this.options.multiSelectOnShift && this.selected.length === 1) {
+ this.selected.splice(0, 1);
+ }
+ this.selected.push(row);
+ this.body.onSelect({ rows: [row] });
+ }
+ }
+ this.prevIndex = index;
+ } else {
+ this.selected = row;
+ this.body.onSelect({ rows: [row] });
+ }
+ }
+ }
+ }, {
+ key: "selectRowsBetween",
+ value: function selectRowsBetween(index) {
+ var reverse = index < this.prevIndex,
+ selecteds = [];
- maxWidth: undefined,
+ for (var i = 0, len = this.body.rows.length; i < len; i++) {
+ var row = this.body.rows[i],
+ greater = i >= this.prevIndex && i <= index,
+ lesser = i <= this.prevIndex && i >= index;
- width: 150,
+ var range = {};
+ if (reverse) {
+ range = {
+ start: index,
+ end: this.prevIndex - index
+ };
+ } else {
+ range = {
+ start: this.prevIndex,
+ end: index + 1
+ };
+ }
- resizable: true,
+ if (reverse && lesser || !reverse && greater) {
+ var idx = this.selected.indexOf(row);
- comparator: undefined,
+ if (reverse && idx > -1) {
+ this.selected.splice(idx, 1);
+ continue;
+ }
- sortable: true,
+ if (i >= range.start && i < range.end) {
+ if (idx === -1) {
+ this.selected.push(row);
+ selecteds.push(row);
+ }
+ }
+ }
+ }
- sort: undefined,
+ this.body.onSelect({ rows: selecteds });
+ }
+ }]);
- sortBy: undefined,
+ return SelectionController;
+}();
- headerRenderer: undefined,
+function SelectionDirective() {
+ return {
+ controller: SelectionController,
+ restrict: 'A',
+ require: '^dtBody',
+ controllerAs: 'selCtrl'
+ };
+}
- cellRenderer: undefined,
+var RowController = function () {
+ function RowController() {
+ _classCallCheck(this, RowController);
+ }
- cellDataGetter: undefined,
+ _createClass(RowController, [{
+ key: "getValue",
+ value: function getValue(col) {
+ if (!col.prop) return '';
+ return DeepValueGetter(this.row, col.prop);
+ }
+ }, {
+ key: "onTreeToggled",
+ value: function onTreeToggled(cell) {
+ this.onTreeToggle({
+ cell: cell,
+ row: this.row
+ });
+ }
+ }, {
+ key: "stylesByGroup",
+ value: function stylesByGroup(group) {
+ var styles = {
+ width: this.columnWidths[group] + 'px'
+ };
- isTreeColumn: false,
+ if (group === 'left') {
+ TranslateXY(styles, this.options.internal.offsetX, 0);
+ } else if (group === 'right') {
+ var offset = (this.columnWidths.total - this.options.internal.innerWidth - this.options.internal.offsetX + this.options.internal.scrollBarWidth) * -1;
+ TranslateXY(styles, offset, 0);
+ }
- isCheckboxColumn: false,
+ return styles;
+ }
+ }, {
+ key: "onCheckboxChanged",
+ value: function onCheckboxChanged(ev) {
+ this.onCheckboxChange({
+ $event: ev,
+ row: this.row
+ });
+ }
+ }]);
- headerCheckbox: false,
+ return RowController;
+}();
- canAutoResize: true
+function RowDirective() {
+ return {
+ restrict: 'E',
+ controller: RowController,
+ controllerAs: 'rowCtrl',
+ scope: true,
+ bindToController: {
+ row: '=',
+ columns: '=',
+ columnWidths: '=',
+ expanded: '=',
+ selected: '=',
+ hasChildren: '=',
+ options: '=',
+ onCheckboxChange: '&',
+ onTreeToggle: '&'
+ },
+ link: function link($scope, $elm, $attrs, ctrl) {
+ if (ctrl.row) {
+ TranslateXY($elm[0].style, 0, ctrl.row.$$index * ctrl.options.rowHeight);
+ }
-};
+ ctrl.options.internal.styleTranslator.register($scope.$index, $elm);
+ },
+ template: "\n \n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
",
+ replace: true
+ };
+}
-var TableDefaults = {
- scrollbarV: true,
+var GroupRowController = function () {
+ function GroupRowController() {
+ _classCallCheck(this, GroupRowController);
+ }
- rowHeight: 30,
+ _createClass(GroupRowController, [{
+ key: "onGroupToggled",
+ value: function onGroupToggled(evt) {
+ evt.stopPropagation();
+ this.onGroupToggle({
+ group: this.row
+ });
+ }
+ }, {
+ key: "treeClass",
+ value: function treeClass() {
+ return {
+ 'dt-tree-toggle': true,
+ 'icon-right': !this.expanded,
+ 'icon-down': this.expanded
+ };
+ }
+ }]);
- columnMode: 'standard',
+ return GroupRowController;
+}();
- loadingMessage: 'Loading...',
+function GroupRowDirective() {
+ return {
+ restrict: 'E',
+ controller: GroupRowController,
+ controllerAs: 'group',
+ bindToController: {
+ row: '=',
+ onGroupToggle: '&',
+ expanded: '=',
+ options: '='
+ },
+ scope: true,
+ replace: true,
+ template: "\n \n \n \n \n \n
",
+ link: function link($scope, $elm, $attrs, ctrl) {
+ TranslateXY($elm[0].style, 0, ctrl.row.$$index * ctrl.options.rowHeight);
- emptyMessage: 'No data to display',
+ ctrl.options.internal.styleTranslator.register($scope.$index, $elm);
+ }
+ };
+}
- headerHeight: 30,
+var CellController = function () {
+ function CellController() {
+ _classCallCheck(this, CellController);
+ }
- footerHeight: 0,
+ _createClass(CellController, [{
+ key: "styles",
+ value: function styles() {
+ return {
+ width: this.column.width + 'px',
+ 'min-width': this.column.width + 'px'
+ };
+ }
+ }, {
+ key: "cellClass",
+ value: function cellClass() {
+ var style = {
+ 'dt-tree-col': this.column.isTreeColumn
+ };
- paging: {
- externalPaging: false,
+ if (this.column.className) {
+ style[this.column.className] = true;
+ }
- size: undefined,
+ return style;
+ }
+ }, {
+ key: "treeClass",
+ value: function treeClass() {
+ return {
+ 'dt-tree-toggle': true,
+ 'icon-right': !this.expanded,
+ 'icon-down': this.expanded
+ };
+ }
+ }, {
+ key: "onTreeToggled",
+ value: function onTreeToggled(evt) {
+ evt.stopPropagation();
+ this.expanded = !this.expanded;
+ this.onTreeToggle({
+ cell: {
+ value: this.value,
+ column: this.column,
+ expanded: this.expanded
+ }
+ });
+ }
+ }, {
+ key: "onCheckboxChanged",
+ value: function onCheckboxChanged(event) {
+ event.stopPropagation();
+ this.onCheckboxChange({ $event: event });
+ }
+ }, {
+ key: "getValue",
+ value: function getValue() {
+ var val = this.column.cellDataGetter ? this.column.cellDataGetter(this.value) : this.value;
- count: 0,
+ if (val === undefined || val === null) val = '';
+ return val;
+ }
+ }]);
- offset: 0,
+ return CellController;
+}();
- loadingIndicator: false
- },
+function CellDirective($rootScope, $compile, $log, $timeout) {
+ return {
+ restrict: 'E',
+ controller: CellController,
+ scope: true,
+ controllerAs: 'cell',
+ bindToController: {
+ options: '=',
+ value: '=',
+ selected: '=',
+ column: '=',
+ row: '=',
+ expanded: '=',
+ hasChildren: '=',
+ onTreeToggle: '&',
+ onCheckboxChange: '&'
+ },
+ template: "\n \n \n \n \n \n
",
+ replace: true,
+ compile: function compile() {
+ return {
+ pre: function pre($scope, $elm, $attrs, ctrl) {
+ var content = _angular2.default.element($elm[0].querySelector('.dt-cell-content')),
+ cellScope;
- selectable: false,
+ if (ctrl.column.template || ctrl.column.cellRenderer) {
+ createCellScope();
+ }
- multiSelect: false,
+ $scope.$watch('cell.row', function () {
+ if (cellScope) {
+ cellScope.$destroy();
- checkboxSelection: false,
+ createCellScope();
- reorderable: true,
+ cellScope.$cell = ctrl.value;
+ cellScope.$row = ctrl.row;
+ cellScope.$column = ctrl.column;
+ cellScope.$$watchers = null;
+ }
- internal: {
- offsetX: 0,
- offsetY: 0,
- innerWidth: 0,
- bodyHeight: 300
- }
+ if (ctrl.column.template) {
+ content.empty();
+ var elm = _angular2.default.element("" + ctrl.column.template.trim() + " ");
+ content.append($compile(elm)(cellScope));
+ } else if (ctrl.column.cellRenderer) {
+ content.empty();
+ var elm = _angular2.default.element(ctrl.column.cellRenderer(cellScope, content));
+ content.append($compile(elm)(cellScope));
+ } else {
+ content[0].innerHTML = ctrl.getValue();
+ }
+ }, true);
-};
+ function createCellScope() {
+ cellScope = ctrl.options.$outer.$new(false);
+ cellScope.getValue = ctrl.getValue;
+ }
+ }
+ };
+ }
+ };
+}
-var DataTableController = function () {
- DataTableController.$inject = ["$scope", "$filter", "$log", "$transclude"];
- function DataTableController($scope, $filter, $log, $transclude) {
+var FooterController = function () {
+ function FooterController($scope) {
var _this6 = this;
- _classCallCheck(this, DataTableController);
+ _classCallCheck(this, FooterController);
- Object.assign(this, {
- $scope: $scope,
- $filter: $filter,
- $log: $log
+ this.page = this.paging.offset + 1;
+ $scope.$watch('footer.paging.offset', function (newVal) {
+ _this6.offsetChanged(newVal);
});
+ }
- this.defaults();
+ _createClass(FooterController, [{
+ key: "offsetChanged",
+ value: function offsetChanged(newVal) {
+ this.page = newVal + 1;
+ }
+ }, {
+ key: "onPaged",
+ value: function onPaged(page) {
+ this.paging.offset = page - 1;
+ this.onPage({
+ offset: this.paging.offset,
+ size: this.paging.size
+ });
+ }
+ }]);
- this.options.$outer = $scope.$parent;
+ return FooterController;
+}();
- $scope.$watch('dt.options.columns', function (newVal, oldVal) {
- _this6.transposeColumnDefaults();
+function FooterDirective() {
+ return {
+ restrict: 'E',
+ controller: FooterController,
+ controllerAs: 'footer',
+ scope: true,
+ bindToController: {
+ paging: '=',
+ onPage: '&'
+ },
+ template: "",
+ replace: true
+ };
+}
- if (newVal.length !== oldVal.length) {
- _this6.adjustColumns();
- }
+var PagerController = function () {
+ function PagerController($scope) {
+ var _this7 = this;
- _this6.calculateColumns();
- }, true);
+ _classCallCheck(this, PagerController);
- var watch = $scope.$watch('dt.rows', function (newVal) {
- if (newVal) {
- watch();
- _this6.onSorted();
- }
+ $scope.$watch('pager.count', function (newVal) {
+ _this7.calcTotalPages(_this7.size, _this7.count);
+ _this7.getPages(_this7.page || 1);
});
- }
-
- _createClass(DataTableController, [{
- key: "defaults",
- value: function defaults() {
- var _this7 = this;
- this.expanded = this.expanded || {};
+ $scope.$watch('pager.size', function (newVal) {
+ _this7.calcTotalPages(_this7.size, _this7.count);
+ _this7.getPages(_this7.page || 1);
+ });
- this.options = angular.extend(angular.copy(TableDefaults), this.options);
+ $scope.$watch('pager.page', function (newVal) {
+ if (newVal !== 0 && newVal <= _this7.totalPages) {
+ _this7.getPages(newVal);
+ }
+ });
- angular.forEach(TableDefaults.paging, function (v, k) {
- if (!_this7.options.paging[k]) {
- _this7.options.paging[k] = v;
- }
- });
+ this.getPages(this.page || 1);
+ }
- if (this.options.selectable && this.options.multiSelect) {
- this.selected = this.selected || [];
- }
+ _createClass(PagerController, [{
+ key: "calcTotalPages",
+ value: function calcTotalPages(size, count) {
+ var count = size < 1 ? 1 : Math.ceil(count / size);
+ this.totalPages = Math.max(count || 0, 1);
}
}, {
- key: "transposeColumnDefaults",
- value: function transposeColumnDefaults() {
- for (var i = 0, len = this.options.columns.length; i < len; i++) {
- var column = this.options.columns[i];
- column.$id = ObjectId();
-
- angular.forEach(ColumnDefaults, function (v, k) {
- if (!column.hasOwnProperty(k)) {
- column[k] = v;
- }
+ key: "selectPage",
+ value: function selectPage(num) {
+ if (num > 0 && num <= this.totalPages) {
+ this.page = num;
+ this.onPage({
+ page: num
});
-
- if (column.name && !column.prop) {
- column.prop = CamelCase(column.name);
- }
-
- this.options.columns[i] = column;
}
}
}, {
- key: "calculateColumns",
- value: function calculateColumns() {
- var columns = this.options.columns;
- this.columnsByPin = ColumnsByPin(columns);
- this.columnWidths = ColumnGroupWidths(this.columnsByPin, columns);
+ key: "prevPage",
+ value: function prevPage() {
+ if (this.page > 1) {
+ this.selectPage(--this.page);
+ }
}
}, {
- key: "tableCss",
- value: function tableCss() {
- return {
- 'fixed': this.options.scrollbarV,
- 'selectable': this.options.selectable,
- 'checkboxable': this.options.checkboxSelection
- };
+ key: "nextPage",
+ value: function nextPage() {
+ this.selectPage(++this.page);
}
}, {
- key: "adjustColumns",
- value: function adjustColumns(forceIdx) {
- var width = this.options.internal.innerWidth - this.options.internal.scrollBarWidth;
-
- if (this.options.columnMode === 'force') {
- ForceFillColumnWidths(this.options.columns, width, forceIdx);
- } else if (this.options.columnMode === 'flex') {
- AdjustColumnWidths(this.options.columns, width);
- }
+ key: "canPrevious",
+ value: function canPrevious() {
+ return this.page > 1;
}
}, {
- key: "calculatePageSize",
- value: function calculatePageSize() {
- this.options.paging.size = Math.ceil(this.options.internal.bodyHeight / this.options.rowHeight) + 1;
+ key: "canNext",
+ value: function canNext() {
+ return this.page < this.totalPages;
}
}, {
- key: "onSorted",
- value: function onSorted() {
- if (!this.rows) return;
+ key: "getPages",
+ value: function getPages(page) {
+ var pages = [],
+ startPage = 1,
+ endPage = this.totalPages,
+ maxSize = 5,
+ isMaxSized = maxSize < this.totalPages;
- var sorts = this.options.columns.filter(function (c) {
- return c.sort;
- }).sort(function (a, b) {
- if (a.sortPriority && b.sortPriority) {
- if (a.sortPriority > b.sortPriority) return 1;
- if (a.sortPriority < b.sortPriority) return -1;
- } else if (a.sortPriority) {
- return -1;
- } else if (b.sortPriority) {
- return 1;
- }
+ if (isMaxSized) {
+ startPage = (Math.ceil(page / maxSize) - 1) * maxSize + 1;
+ endPage = Math.min(startPage + maxSize - 1, this.totalPages);
+ }
- return 0;
- }).map(function (c, i) {
- c.sortPriority = i + 1;
- return c;
- });
+ for (var number = startPage; number <= endPage; number++) {
+ pages.push({
+ number: number,
+ text: number,
+ active: number === page
+ });
+ }
- if (sorts.length) {
- this.onSort({ sorts: sorts });
+ this.pages = pages;
+ }
+ }]);
+
+ return PagerController;
+}();
+
+function PagerDirective() {
+ return {
+ restrict: 'E',
+ controller: PagerController,
+ controllerAs: 'pager',
+ scope: true,
+ bindToController: {
+ page: '=',
+ size: '=',
+ count: '=',
+ onPage: '&'
+ },
+ template: "",
+ replace: true
+ };
+}
+
+function PopoverDirective($q, $timeout, $templateCache, $compile, PopoverRegistry, PositionHelper, $animate) {
+ function loadTemplate(template, plain) {
+ if (!template) {
+ return '';
+ }
+
+ if (_angular2.default.isString(template) && plain) {
+ return template;
+ }
+
+ return $templateCache.get(template) || $http.get(template, { cache: true });
+ }
+
+ function toBoolean(value) {
+ if (value && value.length !== 0) {
+ var v = ("" + value).toLowerCase();
+ value = v == 'true';
+ } else {
+ value = false;
+ }
+ return value;
+ }
+
+ return {
+ restrict: 'A',
+ scope: true,
+ replace: false,
+ link: function link($scope, $element, $attributes) {
+ $scope.popover = null;
+ $scope.popoverId = Date.now();
+
+ $scope.options = {
+ text: $attributes.popoverText,
+ template: $attributes.popoverTemplate,
+ plain: toBoolean($attributes.popoverPlain || false),
+ placement: $attributes.popoverPlacement || 'right',
+ alignment: $attributes.popoverAlignment || 'center',
+ group: $attributes.popoverGroup,
+ spacing: parseInt($attributes.popoverSpacing) || 0,
+ showCaret: toBoolean($attributes.popoverPlain || false)
+ };
+
+ $element.off('mouseenter', display);
+ $element.on('mouseenter', display);
+ $element.off('mouseleave', mouseOut);
+ $element.on('mouseleave', mouseOut);
+
+ function mouseOut() {
+ $scope.exitTimeout = $timeout(remove, 500);
+ }
+
+ function display() {
+ $timeout.cancel($scope.exitTimeout);
+
+ var elm = document.getElementById("#" + $scope.popoverId);
+ if ($scope.popover && elm) return;
- if (this.options.onSort) {
- this.options.onSort(sorts);
+ if ($scope.options.group) {
+ PopoverRegistry.removeGroup($scope.options.group, $scope.popoverId);
}
- var clientSorts = [];
- for (var i = 0, len = sorts.length; i < len; i++) {
- var c = sorts[i];
- if (c.comparator !== false) {
- var dir = c.sort === 'asc' ? '' : '-';
- if (c.sortBy !== undefined) {
- clientSorts.push(dir + c.sortBy);
- } else {
- clientSorts.push(dir + c.prop);
+ if ($scope.options.text && !$scope.options.template) {
+ $scope.popover = _angular2.default.element("
");
+
+ $scope.popover.html($scope.options.text);
+ _angular2.default.element(document.body).append($scope.popover);
+ positionPopover($element, $scope.popover, $scope.options);
+ PopoverRegistry.add($scope.popoverId, { element: $element, popover: $scope.popover, group: $scope.options.group });
+ } else {
+ $q.when(loadTemplate($scope.options.template, $scope.options.plain)).then(function (template) {
+ if (!_angular2.default.isString(template)) {
+ if (template.data && _angular2.default.isString(template.data)) {
+ template = template.data;
+ } else {
+ template = '';
+ }
}
- }
- }
- if (clientSorts.length) {
- var _rows;
+ $scope.popover = _angular2.default.element("
");
- var sortedValues = this.$filter('orderBy')(this.rows, clientSorts);
- this.rows.splice(0, this.rows.length);
- (_rows = this.rows).push.apply(_rows, _toConsumableArray(sortedValues));
+ $scope.popover.html(template);
+ $compile($scope.popover)($scope);
+ _angular2.default.element(document.body).append($scope.popover);
+ positionPopover($element, $scope.popover, $scope.options);
+
+ $scope.popover.off('mouseleave', mouseOut);
+ $scope.popover.on('mouseleave', mouseOut);
+ $scope.popover.on('mouseenter', function () {
+ $timeout.cancel($scope.exitTimeout);
+ });
+
+ PopoverRegistry.add($scope.popoverId, {
+ element: $element,
+ popover: $scope.popover,
+ group: $scope.options.group
+ });
+ });
}
}
- this.options.internal.setYOffset(0);
- }
- }, {
- key: "onTreeToggled",
- value: function onTreeToggled(row, cell) {
- this.onTreeToggle({
- row: row,
- cell: cell
- });
- }
- }, {
- key: "onBodyPage",
- value: function onBodyPage(offset, size) {
- this.onPage({
- offset: offset,
- size: size
- });
- }
- }, {
- key: "onFooterPage",
- value: function onFooterPage(offset, size) {
- var pageBlockSize = this.options.rowHeight * size,
- offsetY = pageBlockSize * offset;
+ function remove() {
+ if ($scope.popover) {
+ $scope.popover.remove();
+ }
- this.options.internal.setYOffset(offsetY);
- }
- }, {
- key: "onHeaderCheckboxChange",
- value: function onHeaderCheckboxChange() {
- if (this.rows) {
- var matches = this.selected.length === this.rows.length;
- this.selected.splice(0, this.selected.length);
+ $scope.popover = undefined;
+ PopoverRegistry.remove($scope.popoverId);
+ }
- if (!matches) {
- var _selected;
+ function positionPopover(triggerElement, popover, options) {
+ $timeout(function () {
+ var elDimensions = triggerElement[0].getBoundingClientRect(),
+ popoverDimensions = popover[0].getBoundingClientRect(),
+ top,
+ left;
+
+ if (options.placement === 'right') {
+ left = elDimensions.left + elDimensions.width + options.spacing;
+ top = PositionHelper.calculateVerticalAlignment(elDimensions, popoverDimensions, options.alignment);
+ }
+ if (options.placement === 'left') {
+ left = elDimensions.left - popoverDimensions.width - options.spacing;
+ top = PositionHelper.calculateVerticalAlignment(elDimensions, popoverDimensions, options.alignment);
+ }
+ if (options.placement === 'top') {
+ top = elDimensions.top - popoverDimensions.height - options.spacing;
+ left = PositionHelper.calculateHorizontalAlignment(elDimensions, popoverDimensions, options.alignment);
+ }
+ if (options.placement === 'bottom') {
+ top = elDimensions.top + elDimensions.height + options.spacing;
+ left = PositionHelper.calculateHorizontalAlignment(elDimensions, popoverDimensions, options.alignment);
+ }
- (_selected = this.selected).push.apply(_selected, _toConsumableArray(this.rows));
+ popover.css({
+ top: top + 'px',
+ left: left + 'px'
+ });
+
+ if ($scope.options.showCaret) {
+ addCaret($scope.popover, elDimensions, popoverDimensions);
+ }
+
+ $animate.addClass($scope.popover, 'popover-animation');
+ }, 50);
+ }
+
+ function addCaret(popoverEl, elDimensions, popoverDimensions) {
+ var caret = _angular2.default.element(" ");
+ popoverEl.append(caret);
+ var caretDimensions = caret[0].getBoundingClientRect();
+
+ var left, top;
+ if ($scope.options.placement === 'right') {
+ left = -6;
+ top = PositionHelper.calculateVerticalCaret(elDimensions, popoverDimensions, caretDimensions, $scope.options.alignment);
}
+ if ($scope.options.placement === 'left') {
+ left = popoverDimensions.width - 2;
+ top = PositionHelper.calculateVerticalCaret(elDimensions, popoverDimensions, caretDimensions, $scope.options.alignment);
+ }
+ if ($scope.options.placement === 'top') {
+ top = popoverDimensions.height - 5;
+ left = PositionHelper.calculateHorizontalCaret(elDimensions, popoverDimensions, caretDimensions, $scope.options.alignment);
+ }
+
+ if ($scope.options.placement === 'bottom') {
+ top = -8;
+ left = PositionHelper.calculateHorizontalCaret(elDimensions, popoverDimensions, caretDimensions, $scope.options.alignment);
+ }
+
+ caret.css({
+ top: top + 'px',
+ left: left + 'px'
+ });
}
}
- }, {
- key: "isAllRowsSelected",
- value: function isAllRowsSelected() {
- if (this.rows) return false;
- return this.selected.length === this.rows.length;
- }
- }, {
- key: "onResized",
- value: function onResized(column, width) {
- var idx = this.options.columns.indexOf(column);
- if (idx > -1) {
- var column = this.options.columns[idx];
- column.width = width;
- column.canAutoResize = false;
+ };
+}
- this.adjustColumns(idx);
- this.calculateColumns();
+function PopoverRegistry($animate) {
+ var popovers = {};
+ this.add = function (id, object) {
+ popovers[id] = object;
+ };
+ this.find = function (id) {
+ popovers[id];
+ };
+ this.remove = function (id) {
+ delete popovers[id];
+ };
+ this.removeGroup = function (group, currentId) {
+ angular.forEach(popovers, function (popoverOb, id) {
+ if (id === currentId) return;
+
+ if (popoverOb.group && popoverOb.group === group) {
+ $animate.removeClass(popoverOb.popover, 'sw-popover-animate').then(function () {
+ popoverOb.popover.remove();
+ delete popovers[id];
+ });
}
+ });
+ };
+}
- if (this.onColumnResize) {
- this.onColumnResize({
- column: column,
- width: width
- });
+function PositionHelper() {
+ return {
+
+ calculateVerticalAlignment: function calculateVerticalAlignment(elDimensions, popoverDimensions, alignment) {
+ if (alignment === 'top') {
+ return elDimensions.top;
+ }
+ if (alignment === 'bottom') {
+ return elDimensions.top + elDimensions.height - popoverDimensions.height;
+ }
+ if (alignment === 'center') {
+ return elDimensions.top + elDimensions.height / 2 - popoverDimensions.height / 2;
+ }
+ },
+
+ calculateVerticalCaret: function calculateVerticalCaret(elDimensions, popoverDimensions, caretDimensions, alignment) {
+ if (alignment === 'top') {
+ return elDimensions.height / 2 - caretDimensions.height / 2 - 1;
+ }
+ if (alignment === 'bottom') {
+ return popoverDimensions.height - elDimensions.height / 2 - caretDimensions.height / 2 - 1;
+ }
+ if (alignment === 'center') {
+ return popoverDimensions.height / 2 - caretDimensions.height / 2 - 1;
+ }
+ },
+
+ calculateHorizontalCaret: function calculateHorizontalCaret(elDimensions, popoverDimensions, caretDimensions, alignment) {
+ if (alignment === 'left') {
+ return elDimensions.width / 2 - caretDimensions.height / 2 - 1;
+ }
+ if (alignment === 'right') {
+ return popoverDimensions.width - elDimensions.width / 2 - caretDimensions.height / 2 - 1;
+ }
+ if (alignment === 'center') {
+ return popoverDimensions.width / 2 - caretDimensions.height / 2 - 1;
+ }
+ },
+
+ calculateHorizontalAlignment: function calculateHorizontalAlignment(elDimensions, popoverDimensions, alignment) {
+ if (alignment === 'left') {
+ return elDimensions.left;
+ }
+ if (alignment === 'right') {
+ return elDimensions.left + elDimensions.width - popoverDimensions.width;
+ }
+ if (alignment === 'center') {
+ return elDimensions.left + elDimensions.width / 2 - popoverDimensions.width / 2;
}
}
- }, {
- key: "onSelected",
- value: function onSelected(rows) {
- this.onSelect({
- rows: rows
+
+ };
+}
+
+var popover = _angular2.default.module('dt.popover', []).service('PopoverRegistry', PopoverRegistry).factory('PositionHelper', PositionHelper).directive('popover', PopoverDirective);
+
+var MenuController = function () {
+ function MenuController($scope, $timeout) {
+ _classCallCheck(this, MenuController);
+
+ this.$scope = $scope;
+ }
+
+ _createClass(MenuController, [{
+ key: "getColumnIndex",
+ value: function getColumnIndex(model) {
+ return this.$scope.current.findIndex(function (col) {
+ return model.name == col.name;
});
}
}, {
- key: "onRowClicked",
- value: function onRowClicked(row) {
- this.onRowClick({
- row: row
- });
+ key: "isChecked",
+ value: function isChecked(model) {
+ return this.getColumnIndex(model) > -1;
}
}, {
- key: "onRowDblClicked",
- value: function onRowDblClicked(row) {
- this.onRowDblClick({
- row: row
- });
+ key: "onCheck",
+ value: function onCheck(model) {
+ var idx = this.getColumnIndex(model);
+ if (idx === -1) {
+ this.$scope.current.push(model);
+ } else {
+ this.$scope.current.splice(idx, 1);
+ }
}
}]);
- return DataTableController;
+ return MenuController;
}();
-function DataTableDirective($window, $timeout, $parse) {
+function MenuDirective() {
return {
restrict: 'E',
- replace: true,
- controller: DataTableController,
- scope: true,
- bindToController: {
- options: '=',
- rows: '=',
- selected: '=?',
- expanded: '=?',
- onSelect: '&',
- onSort: '&',
- onTreeToggle: '&',
- onPage: '&',
- onRowClick: '&',
- onRowDblClick: '&',
- onColumnResize: '&'
+ controller: 'MenuController',
+ controllerAs: 'dtm',
+ scope: {
+ current: '=',
+ available: '='
},
- controllerAs: 'dt',
- template: function template(element) {
- var columns = element[0].getElementsByTagName('column'),
- id = ObjectId();
- DataTableService.saveColumns(id, columns);
+ template: ""
+ };
+}
- return "\n \n \n \n \n \n \n
";
- },
- compile: function compile(tElem, tAttrs) {
- return {
- pre: function pre($scope, $elm, $attrs, ctrl) {
- DataTableService.buildColumns($scope, $parse);
+var DropdownController = function () {
+ function DropdownController($scope) {
+ _classCallCheck(this, DropdownController);
- var id = $elm.attr('data-column-id'),
- columns = DataTableService.columns[id];
- if (columns) {
- ctrl.options.columns = columns;
- }
+ $scope.open = false;
+ }
- ctrl.transposeColumnDefaults();
- ctrl.options.internal.scrollBarWidth = ScrollbarWidth();
+ _createClass(DropdownController, [{
+ key: "toggle",
+ value: function toggle(scope) {
+ scope.open = !scope.open;
+ }
+ }]);
- function resize() {
- var rect = $elm[0].getBoundingClientRect();
+ return DropdownController;
+}();
- ctrl.options.internal.innerWidth = Math.floor(rect.width);
+function DropdownDirective($document, $timeout) {
+ return {
+ restrict: 'C',
+ controller: 'DropdownController',
+ link: function link($scope, $elm, $attrs) {
- if (ctrl.options.scrollbarV) {
- var height = rect.height;
+ function closeDropdown(ev) {
+ if ($elm[0].contains(ev.target)) {
+ return;
+ }
- if (ctrl.options.headerHeight) {
- height = height - ctrl.options.headerHeight;
- }
+ $timeout(function () {
+ $scope.open = false;
+ off();
+ });
+ }
- if (ctrl.options.footerHeight) {
- height = height - ctrl.options.footerHeight;
- }
+ function keydown(ev) {
+ if (ev.which === 27) {
+ $timeout(function () {
+ $scope.open = false;
+ off();
+ });
+ }
+ }
- ctrl.options.internal.bodyHeight = height;
- ctrl.calculatePageSize();
- }
+ function off() {
+ $document.unbind('click', closeDropdown);
+ $document.unbind('keydown', keydown);
+ }
- ctrl.adjustColumns();
- };
+ $scope.$watch('open', function (newVal) {
+ if (newVal) {
+ $document.bind('click', closeDropdown);
+ $document.bind('keydown', keydown);
+ }
+ });
+ }
+ };
+}
- $window.addEventListener('resize', throttle(function () {
- $timeout(resize);
- }));
+function DropdownToggleDirective($timeout) {
+ return {
+ restrict: 'C',
+ controller: 'DropdownController',
+ require: '?^dropdown',
+ link: function link($scope, $elm, $attrs, ctrl) {
- var checkVisibility = function checkVisibility() {
- var bounds = $elm[0].getBoundingClientRect(),
- visible = bounds.width && bounds.height;
- if (visible) resize();else $timeout(checkVisibility, 100);
- };
- checkVisibility();
+ function toggleClick(event) {
+ event.preventDefault();
+ $timeout(function () {
+ ctrl.toggle($scope);
+ });
+ }
- $elm.addClass('dt-loaded');
+ function toggleDestroy() {
+ $elm.unbind('click', toggleClick);
+ }
- $scope.$on('$destroy', function () {
- angular.element($window).off('resize');
- });
- }
- };
+ $elm.bind('click', toggleClick);
+ $scope.$on('$destroy', toggleDestroy);
+ }
+ };
+}
+
+function DropdownMenuDirective($animate) {
+ return {
+ restrict: 'C',
+ require: '?^dropdown',
+ link: function link($scope, $elm, $attrs, ctrl) {
+ $scope.$watch('open', function () {
+ $animate[$scope.open ? 'addClass' : 'removeClass']($elm, 'ddm-open');
+ });
}
};
}
-var dataTable = angular.module('data-table', []).directive('dtable', DataTableDirective).directive('resizable', ResizableDirective).directive('sortable', SortableDirective).directive('dtHeader', HeaderDirective).directive('dtHeaderCell', HeaderCellDirective).directive('dtBody', BodyDirective).directive('dtScroller', ScrollerDirective).directive('dtSeletion', SelectionDirective).directive('dtRow', RowDirective).directive('dtGroupRow', GroupRowDirective).directive('dtCell', CellDirective).directive('dtFooter', FooterDirective).directive('dtPager', PagerDirective);
+var dropdown = _angular2.default.module('dt.dropdown', []).controller('DropdownController', DropdownController).directive('dropdown', DropdownDirective).directive('dropdownToggle', DropdownToggleDirective).directive('dropdownMenu', DropdownMenuDirective);
+
+var menu = _angular2.default.module('dt.menu', [dropdown.name]).controller('MenuController', MenuController).directive('dtm', MenuDirective);
+
+var dataTable = _angular2.default.module('data-table', []).directive('dtable', DataTableDirective).directive('resizable', ResizableDirective).directive('sortable', SortableDirective).directive('dtHeader', HeaderDirective).directive('dtHeaderCell', HeaderCellDirective).directive('dtBody', BodyDirective).directive('dtScroller', ScrollerDirective).directive('dtSeletion', SelectionDirective).directive('dtRow', RowDirective).directive('dtGroupRow', GroupRowDirective).directive('dtCell', CellDirective).directive('dtFooter', FooterDirective).directive('dtPager', PagerDirective);
+exports.dtPopover = popover;
+exports.dtMenu = menu;
exports.default = dataTable;
\ No newline at end of file
diff --git a/release/dataTable.css b/release/dataTable.css
index a8c67a8..7e7a00b 100644
--- a/release/dataTable.css
+++ b/release/dataTable.css
@@ -4,6 +4,151 @@
justify-content: center;
position: relative;
}
+.dt .popover {
+ position: absolute;
+ background: #fff;
+ color: #999;
+ z-index: 5000;
+ opacity: 0;
+ display: block;
+ max-width: 250px;
+ max-height: 300px;
+ overflow-y: auto;
+ -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 2px 0 rgba(0, 0, 0, 0.24);
+ -moz-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 2px 0 rgba(0, 0, 0, 0.24);
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 2px 0 rgba(0, 0, 0, 0.24);
+}
+.dt .popover h1,
+.dt .popover h2,
+.dt .popover h3,
+.dt .popover h4,
+.dt .popover h5,
+.dt .popover h6 {
+ color: #272e33 !important;
+}
+.dt .popover .popover-caret {
+ position: absolute;
+ z-index: 5001;
+ min-width: 6px;
+ height: 11px;
+}
+.dt .popover .popover-caret.caret-left {
+ -webkit-transform: rotate(180deg);
+ -moz-transform: rotate(180deg);
+ -ms-transform: rotate(180deg);
+ -o-transform: rotate(180deg);
+ transform: rotate(180deg);
+}
+.dt .popover .popover-caret.caret-top {
+ -webkit-transform: rotate(-90deg);
+ -moz-transform: rotate(-90deg);
+ -ms-transform: rotate(-90deg);
+ -o-transform: rotate(-90deg);
+ transform: rotate(-90deg);
+}
+.dt .popover .popover-caret.caret-bottom {
+ -webkit-transform: rotate(90deg);
+ -moz-transform: rotate(90deg);
+ -ms-transform: rotate(90deg);
+ -o-transform: rotate(90deg);
+ transform: rotate(90deg);
+}
+.dt .popover header {
+ padding: 15px 20px;
+}
+.dt .popover header h1 {
+ font-size: 16px;
+ font-weight: 600;
+ margin: 0;
+}
+.dt .popover header a,
+.dt .popover header a:hover,
+.dt .popover header a:focus {
+ color: #5ea1df;
+}
+.dt .popover p {
+ color: #999 !important;
+}
+.dt .popover .list {
+ list-style-type: none;
+ margin: 0px;
+ padding: 0px;
+}
+.dt .popover .list .main-text {
+ display: block;
+ color: #73777b;
+}
+.dt .popover .list .sub-text {
+ color: #afafaf;
+ font-size: 12px;
+}
+.dt .popover .list li {
+ border-top: 1px solid #f1f1f1;
+ margin: 0;
+ background: #fff;
+}
+.dt .popover .list li .list-link {
+ padding: 10px 20px;
+ display: block;
+ cursor: pointer;
+}
+.dt .popover .list li:hover {
+ background: #eff5fc;
+}
+.dt .popover .list .inactive,
+.dt .popover .list .inactive:hover {
+ padding: 10px 20px;
+ background: none;
+}
+.dt .popover-text {
+ padding: 10px;
+ color: #000;
+ font-weight: 600;
+ font-size: 12px;
+}
+.dt .popover-right {
+ -webkit-transform: translate3d(10px, 0, 0);
+ transform: translate3d(10, 0, 0);
+}
+.dt .popover-left {
+ -webkit-transform: translate3d(-10px, 0, 0);
+ transform: translate3d(-10px, 0, 0);
+}
+.dt .popover-top {
+ -webkit-transform: translate3d(0, -10px, 0);
+ transform: translate3d(0, -10px, 0);
+}
+.dt .popover-bottom {
+ -webkit-transform: translate3d(0, 10px, 0);
+ transform: translate3d(0, 10px, 0);
+}
+.dt .popover-animation {
+ opacity: 1;
+ -webkit-transition: opacity 0.3s, -webkit-transform 0.3s;
+ transition: opacity 0.3s, transform 0.3s;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+}
+.dt .dt-menu {
+ text-align: left;
+}
+.dt .dt-menu ul,
+.dt .dt-menu li {
+ padding: 0;
+ margin: 0;
+ list-style: none;
+}
+.dt .dt-menu .dropdown-menu {
+ width: 200px;
+ display: none;
+}
+.dt .dt-menu .dropdown-menu.ddm-open {
+ display: inline-block;
+}
+.dt .dt-menu ul {
+ max-height: 300px;
+ overflow-y: auto;
+}
.dt.dt-loaded {
visibility: visible !important;
}
diff --git a/release/dataTable.es6.js b/release/dataTable.es6.js
index 3a3f3b9..18a83a5 100644
--- a/release/dataTable.es6.js
+++ b/release/dataTable.es6.js
@@ -1,3 +1,5 @@
+import angular$1 from 'angular';
+
/**
* Array.prototype.find()
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
@@ -37,526 +39,368 @@
}
}());
-class PagerController {
-
- /**
- * Creates an instance of the Pager Controller
- * @param {object} $scope
- */
- /*@ngInject*/
- constructor($scope){
- $scope.$watch('pager.count', (newVal) => {
- this.calcTotalPages(this.size, this.count);
- this.getPages(this.page || 1);
- });
-
- $scope.$watch('pager.size', (newVal) => {
- this.calcTotalPages(this.size, this.count);
- this.getPages(this.page || 1);
- });
-
- $scope.$watch('pager.page', (newVal) => {
- if (newVal !== 0 && newVal <= this.totalPages) {
- this.getPages(newVal);
+/**
+ * Resizable directive
+ * http://stackoverflow.com/questions/18368485/angular-js-resizable-div-directive
+ * @param {object}
+ * @param {function}
+ * @param {function}
+ */
+function ResizableDirective($document, $timeout){
+ return {
+ restrict: 'A',
+ scope:{
+ isResizable: '=resizable',
+ minWidth: '=',
+ maxWidth: '=',
+ onResize: '&'
+ },
+ link: function($scope, $element, $attrs){
+ if($scope.isResizable){
+ $element.addClass('resizable');
}
- });
-
- this.getPages(this.page || 1);
- }
- /**
- * Calculates the total number of pages given the count.
- * @return {int} page count
- */
- calcTotalPages(size, count) {
- var count = size < 1 ? 1 : Math.ceil(count / size);
- this.totalPages = Math.max(count || 0, 1);
- }
+ var handle = angular.element(` `),
+ parent = $element.parent(),
+ prevScreenX;
- /**
- * Select a page
- * @param {int} num
- */
- selectPage(num){
- if (num > 0 && num <= this.totalPages) {
- this.page = num;
- this.onPage({
- page: num
- });
- }
- }
+ handle.on('mousedown', function(event) {
+ if(!$element[0].classList.contains('resizable')) {
+ return false;
+ }
- /**
- * Selects the previous pager
- */
- prevPage(){
- if (this.page > 1) {
- this.selectPage(--this.page);
- }
- }
+ event.stopPropagation();
+ event.preventDefault();
- /**
- * Selects the next page
- */
- nextPage(){
- this.selectPage(++this.page);
- }
+ $document.on('mousemove', mousemove);
+ $document.on('mouseup', mouseup);
+ });
- /**
- * Determines if the pager can go previous
- * @return {boolean}
- */
- canPrevious(){
- return this.page > 1;
- }
+ function mousemove(event) {
+ event = event.originalEvent || event;
- /**
- * Determines if the pager can go forward
- * @return {boolean}
- */
- canNext(){
- return this.page < this.totalPages;
- }
+ var width = parent[0].clientWidth,
+ movementX = event.movementX || event.mozMovementX || (event.screenX - prevScreenX),
+ newWidth = width + (movementX || 0);
- /**
- * Gets the page set given the current page
- * @param {int} page
- */
- getPages(page) {
- var pages = [],
- startPage = 1,
- endPage = this.totalPages,
- maxSize = 5,
- isMaxSized = maxSize < this.totalPages;
+ prevScreenX = event.screenX;
- if (isMaxSized) {
- startPage = ((Math.ceil(page / maxSize) - 1) * maxSize) + 1;
- endPage = Math.min(startPage + maxSize - 1, this.totalPages);
- }
+ if((!$scope.minWidth || newWidth >= $scope.minWidth) && (!$scope.maxWidth || newWidth <= $scope.maxWidth)){
+ parent.css({
+ width: newWidth + 'px'
+ });
+ }
+ }
- for (var number = startPage; number <= endPage; number++) {
- pages.push({
- number: number,
- text: number,
- active: number === page
- });
- }
+ function mouseup() {
+ if ($scope.onResize) {
+ $timeout(function () {
+ let width = parent[0].clientWidth;
+ if (width < $scope.minWidth){
+ width = $scope.minWidth;
+ }
+ $scope.onResize({ width: width });
+ });
+ }
- /*
- if (isMaxSized) {
- if (startPage > 1) {
- pages.unshift({
- number: startPage - 1,
- text: '...'
- });
+ $document.unbind('mousemove', mousemove);
+ $document.unbind('mouseup', mouseup);
}
- if (endPage < this.totalPages) {
- pages.push({
- number: endPage + 1,
- text: '...'
- });
- }
+ $element.append(handle);
}
- */
-
- this.pages = pages;
- }
-
+ };
}
-function PagerDirective(){
+/**
+ * Sortable Directive
+ * http://jsfiddle.net/RubaXa/zLq5J/3/
+ * https://jsfiddle.net/hrohxze0/6/
+ * @param {function}
+ */
+function SortableDirective($timeout) {
return {
- restrict: 'E',
- controller: PagerController,
- controllerAs: 'pager',
- scope: true,
- bindToController: {
- page: '=',
- size: '=',
- count: '=',
- onPage: '&'
+ restrict: 'A',
+ scope: {
+ isSortable: '=sortable',
+ onSortableSort: '&'
},
- template:
- ``,
- replace: true
- };
-}
+ link: function($scope, $element, $attrs){
+ var rootEl = $element[0], dragEl, nextEl, dropEl;
-class FooterController {
+ function isbefore(a, b) {
+ if (a.parentNode == b.parentNode) {
+ for (var cur = a; cur; cur = cur.previousSibling) {
+ if (cur === b) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
- /**
- * Creates an instance of the Footer Controller
- * @param {scope}
- * @return {[type]}
- */
- /*@ngInject*/
- constructor($scope){
- this.page = this.paging.offset + 1;
- $scope.$watch('footer.paging.offset', (newVal) => {
- this.offsetChanged(newVal)
- });
- }
+ function onDragEnter(e) {
+ var target = e.target;
+ if (isbefore(dragEl, target)) {
+ target.parentNode.insertBefore(dragEl, target);
+ } else if(target.nextSibling && target.hasAttribute('draggable')) {
+ target.parentNode.insertBefore(dragEl, target.nextSibling.nextSibling);
+ }
+ }
- /**
- * The offset ( page ) changed externally, update the page
- * @param {new offset}
- */
- offsetChanged(newVal){
- this.page = newVal + 1;
- }
+ function onDragEnd(evt) {
+ evt.preventDefault();
- /**
- * The pager was invoked
- * @param {scope}
- */
- onPaged(page){
- this.paging.offset = page - 1;
- this.onPage({
- offset: this.paging.offset,
- size: this.paging.size
- });
- }
+ dragEl.classList.remove('dt-clone');
-}
+ $element.off('dragend', onDragEnd);
+ $element.off('dragenter', onDragEnter);
-function FooterDirective(){
- return {
- restrict: 'E',
- controller: FooterController,
- controllerAs: 'footer',
- scope: true,
- bindToController: {
- paging: '=',
- onPage: '&'
- },
- template:
- ``,
- replace: true
- };
-}
+ if (nextEl !== dragEl.nextSibling) {
+ $scope.onSortableSort({
+ event: evt,
+ columnId: angular$1.element(dragEl).attr('data-id')
+ });
+ }
+ }
-class CellController {
+ function onDragStart(evt){
+ if(!$scope.isSortable) return false;
+ evt = evt.originalEvent || evt;
- /**
- * Calculates the styles for the Cell Directive
- * @return {styles object}
- */
- styles(){
- return {
- width: this.column.width + 'px',
- 'min-width': this.column.width + 'px'
- };
- }
+ dragEl = evt.target;
+ nextEl = dragEl.nextSibling;
+ dragEl.classList.add('dt-clone');
- /**
- * Calculates the css classes for the cell directive
- * @param {column}
- * @return {class object}
- */
- cellClass(){
- var style = {
- 'dt-tree-col': this.column.isTreeColumn
- };
+ evt.dataTransfer.effectAllowed = 'move';
+ evt.dataTransfer.setData('Text', dragEl.textContent);
- if(this.column.className){
- style[this.column.className] = true;
- }
+ $element.on('dragenter', onDragEnter);
+ $element.on('dragend', onDragEnd);
+ }
- return style;
- }
+ $element.on('dragstart', onDragStart);
- /**
- * Calculates the tree class styles.
- * @return {css classes object}
- */
- treeClass(){
- return {
- 'dt-tree-toggle': true,
- 'icon-right': !this.expanded,
- 'icon-down': this.expanded
+ $scope.$on('$destroy', () => {
+ $element.off('dragstart', onDragStart);
+ });
}
}
+}
- /**
- * Invoked when the tree toggle button was clicked.
- * @param {event}
- */
- onTreeToggled(evt){
- evt.stopPropagation();
- this.expanded = !this.expanded;
- this.onTreeToggle({
- cell: {
- value: this.value,
- column: this.column,
- expanded: this.expanded
- }
- });
- }
+/**
+ * Default Table Options
+ * @type {object}
+ */
+const TableDefaults = {
- /**
- * Invoked when the checkbox was changed
- * @param {object} event
- */
- onCheckboxChanged(event){
- event.stopPropagation();
- this.onCheckboxChange({ $event: event });
- }
+ // Enable vertical scrollbars
+ scrollbarV: true,
- /**
- * Returns the value in its fomatted form
- * @return {string} value
- */
- getValue(){
- var val = this.column.cellDataGetter ?
- this.column.cellDataGetter(this.value) : this.value;
+ // Enable horz scrollbars
+ // scrollbarH: true,
- if(val === undefined || val === null) val = '';
- return val;
- }
+ // The row height, which is necessary
+ // to calculate the height for the lazy rendering.
+ rowHeight: 30,
-}
+ // flex
+ // force
+ // standard
+ columnMode: 'standard',
-function CellDirective($rootScope, $compile, $log, $timeout){
- return {
- restrict: 'E',
- controller: CellController,
- scope: true,
- controllerAs: 'cell',
- bindToController: {
- options: '=',
- value: '=',
- selected: '=',
- column: '=',
- row: '=',
- expanded: '=',
- hasChildren: '=',
- onTreeToggle: '&',
- onCheckboxChange: '&'
- },
- template:
- `
-
-
-
-
-
-
`,
- replace: true,
- compile: function() {
- return {
- pre: function($scope, $elm, $attrs, ctrl) {
- var content = angular.element($elm[0].querySelector('.dt-cell-content')), cellScope;
+ // Loading message presented when the array is undefined
+ loadingMessage: 'Loading...',
- // extend the outer scope onto our new cell scope
- if(ctrl.column.template || ctrl.column.cellRenderer){
- createCellScope();
- }
+ // Message to show when array is presented
+ // but contains no values
+ emptyMessage: 'No data to display',
- $scope.$watch('cell.row', () => {
- if(cellScope){
- cellScope.$destroy();
+ // The minimum header height in pixels.
+ // pass falsey for no header
+ headerHeight: 30,
- createCellScope();
+ // The minimum footer height in pixels.
+ // pass falsey for no footer
+ footerHeight: 0,
- cellScope.$cell = ctrl.value;
- cellScope.$row = ctrl.row;
- cellScope.$column = ctrl.column;
- cellScope.$$watchers = null;
- }
+ paging: {
+ // if external paging is turned on
+ externalPaging: false,
- if(ctrl.column.template){
- content.empty();
- var elm = angular.element(`${ctrl.column.template.trim()} `);
- content.append($compile(elm)(cellScope));
- } else if(ctrl.column.cellRenderer){
- content.empty();
- var elm = angular.element(ctrl.column.cellRenderer(cellScope, content));
- content.append($compile(elm)(cellScope));
- } else {
- content[0].innerHTML = ctrl.getValue();
- }
-
- }, true);
+ // Page size
+ size: undefined,
- function createCellScope(){
- cellScope = ctrl.options.$outer.$new(false);
- cellScope.getValue = ctrl.getValue;
- }
- }
- }
- }
- };
-}
+ // Total count
+ count: 0,
-var cache = {},
- testStyle = document.createElement('div').style;
+ // Page offset
+ offset: 0,
+ // Loading indicator
+ loadingIndicator: false
+ },
-// Get Prefix
-// http://davidwalsh.name/vendor-prefix
-var prefix = (function () {
- var styles = window.getComputedStyle(document.documentElement, ''),
- pre = (Array.prototype.slice
- .call(styles)
- .join('')
- .match(/-(moz|webkit|ms)-/) || (styles.OLink === '' && ['', 'o'])
- )[1],
- dom = ('WebKit|Moz|MS|O').match(new RegExp('(' + pre + ')', 'i'))[1];
- return {
- dom: dom,
- lowercase: pre,
- css: '-' + pre + '-',
- js: pre[0].toUpperCase() + pre.substr(1)
- };
-})();
+ // if users can select itmes
+ selectable: false,
+ // if users can select mutliple items
+ multiSelect: false,
+
+ // checkbox selection vs row click
+ checkboxSelection: false,
+
+ // if you can reorder columns
+ reorderable: true,
+
+ internal: {
+ offsetX: 0,
+ offsetY: 0,
+ innerWidth: 0,
+ bodyHeight: 300
+ }
+
+};
/**
- * Converts strings from something to camel case
- * http://stackoverflow.com/questions/10425287/convert-dash-separated-string-to-camelcase
- * @param {string} str
- * @return {string} camel case string
+ * Default Column Options
+ * @type {object}
*/
-function CamelCase(str) {
- // Replace special characters with a space
- str = str.replace(/[^a-zA-Z0-9 ]/g, " ");
- // put a space before an uppercase letter
- str = str.replace(/([a-z](?=[A-Z]))/g, '$1 ');
- // Lower case first character and some other stuff
- str = str.replace(/([^a-zA-Z0-9 ])|^[0-9]+/g, '').trim().toLowerCase();
- // uppercase characters preceded by a space or number
- str = str.replace(/([ 0-9]+)([a-zA-Z])/g, function(a,b,c) {
- return b.trim()+c.toUpperCase();
- });
- return str;
-}
+const ColumnDefaults = {
+
+ // pinned to the left
+ frozenLeft: false,
+
+ // pinned to the right
+ frozenRight: false,
+
+ // body cell css class name
+ className: undefined,
+
+ // header cell css class name
+ headerClassName: undefined,
+
+ // The grow factor relative to other columns. Same as the flex-grow
+ // API from http://www.w3.org/TR/css3-flexbox/. Basically,
+ // take any available extra width and distribute it proportionally
+ // according to all columns' flexGrow values.
+ flexGrow: 0,
+
+ // Minimum width of the column.
+ minWidth: 100,
+
+ //Maximum width of the column.
+ maxWidth: undefined,
+
+ // The width of the column, by default (in pixels).
+ width: 150,
+
+ // If yes then the column can be resized, otherwise it cannot.
+ resizable: true,
+
+ // Custom sort comparator
+ // pass false if you want to server sort
+ comparator: undefined,
+
+ // If yes then the column can be sorted.
+ sortable: true,
+
+ // Default sort asecending/descending for the column
+ sort: undefined,
+
+ // If you want to sort a column by a special property
+ // See an example in demos/sort.html
+ sortBy: undefined,
+
+ // The cell renderer that returns content for table column header
+ headerRenderer: undefined,
+
+ // The cell renderer function(scope, elm) that returns React-renderable content for table cell.
+ cellRenderer: undefined,
+
+ // The getter function(value) that returns the cell data for the cellRenderer.
+ // If not provided, the cell data will be collected from row data instead.
+ cellDataGetter: undefined,
+
+ // Adds +/- button and makes a secondary call to load nested data
+ isTreeColumn: false,
+
+ // Adds the checkbox selection to the column
+ isCheckboxColumn: false,
+
+ // Toggles the checkbox column in the header
+ // for selecting all values given to the grid
+ headerCheckbox: false,
+
+ // Whether the column can automatically resize to fill space in the table.
+ canAutoResize: true
+};
/**
- * @param {string} property Name of a css property to check for.
- * @return {?string} property name supported in the browser, or null if not
- * supported.
+ * Shim layer with setTimeout fallback
+ * http://www.html5rocks.com/en/tutorials/speed/animations/
*/
-function GetVendorPrefixedName(property) {
- var name = CamelCase(property)
- if(!cache[name]){
- if(testStyle[prefix.css + property] !== undefined) {
- cache[name] = prefix.css + property;
- } else if(testStyle[property] !== undefined){
- cache[name] = property;
- }
- }
- return cache[name];
-}
+var requestAnimFrame = (function(){
+ return window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ window.msRequestAnimationFrame ||
+ function( callback ){
+ window.setTimeout(callback, 1000 / 60);
+ };
+})();
+/**
+ * Creates a unique object id.
+ */
+function ObjectId() {
+ var timestamp = (new Date().getTime() / 1000 | 0).toString(16);
+ return timestamp + 'xxxxxxxxxxxxxxxx'.replace(/[x]/g, function () {
+ return (Math.random() * 16 | 0).toString(16);
+ }).toLowerCase();
+}
-// browser detection and prefixing tools
-var transform = GetVendorPrefixedName('transform'),
- backfaceVisibility = GetVendorPrefixedName('backfaceVisibility'),
- hasCSSTransforms = !!GetVendorPrefixedName('transform'),
- hasCSS3DTransforms = !!GetVendorPrefixedName('perspective'),
- ua = window.navigator.userAgent,
- isSafari = (/Safari\//).test(ua) && !(/Chrome\//).test(ua);
+/**
+ * Returns the columns by pin.
+ * @param {array} colsumns
+ */
+function ColumnsByPin(cols){
+ var ret = {
+ left: [],
+ center: [],
+ right: []
+ };
-function TranslateXY(styles, x,y){
- if (hasCSSTransforms) {
- if (!isSafari && hasCSS3DTransforms) {
- styles[transform] = `translate3d(${x}px, ${y}px, 0)`;
- styles[backfaceVisibility] = 'hidden';
+ for(var i=0, len=cols.length; i < len; i++) {
+ var c = cols[i];
+ if(c.frozenLeft){
+ ret.left.push(c);
+ } else if(c.frozenRight){
+ ret.right.push(c);
} else {
- styles[CamelCase(transform)] = `translate(${x}px, ${y}px)`;
+ ret.center.push(c);
}
- } else {
- styles.top = y + 'px';
- styles.left = x + 'px';
- }
-}
-
-class GroupRowController {
-
- onGroupToggled(evt){
- evt.stopPropagation();
- this.onGroupToggle({
- group: this.row
- });
- }
-
- treeClass(){
- return {
- 'dt-tree-toggle': true,
- 'icon-right': !this.expanded,
- 'icon-down': this.expanded
- };
}
+ return ret;
}
-function GroupRowDirective(){
+/**
+ * Returns the widths of all group sets of a column
+ * @param {object} groups
+ * @param {array} all
+ */
+function ColumnGroupWidths(groups, all){
return {
- restrict: 'E',
- controller: GroupRowController,
- controllerAs: 'group',
- bindToController: {
- row: '=',
- onGroupToggle: '&',
- expanded: '=',
- options: '='
- },
- scope: true,
- replace:true,
- template: `
-
-
-
-
-
-
`,
- link: function($scope, $elm, $attrs, ctrl){
- // inital render position
- TranslateXY($elm[0].style, 0, ctrl.row.$$index * ctrl.options.rowHeight);
-
- // register w/ the style translator
- ctrl.options.internal.styleTranslator.register($scope.$index, $elm);
- }
+ left: ColumnTotalWidth(groups.left),
+ center: ColumnTotalWidth(groups.center),
+ right: ColumnTotalWidth(groups.right),
+ total: ColumnTotalWidth(all)
};
}
-
/**
* Returns a deep object given a string. zoo['animal.type']
* @param {object} obj
@@ -577,1058 +421,1036 @@ function DeepValueGetter(obj, path) {
return current;
}
-class RowController {
+/**
+ * Converts strings from something to camel case
+ * http://stackoverflow.com/questions/10425287/convert-dash-separated-string-to-camelcase
+ * @param {string} str
+ * @return {string} camel case string
+ */
+function CamelCase(str) {
+ // Replace special characters with a space
+ str = str.replace(/[^a-zA-Z0-9 ]/g, " ");
+ // put a space before an uppercase letter
+ str = str.replace(/([a-z](?=[A-Z]))/g, '$1 ');
+ // Lower case first character and some other stuff
+ str = str.replace(/([^a-zA-Z0-9 ])|^[0-9]+/g, '').trim().toLowerCase();
+ // uppercase characters preceded by a space or number
+ str = str.replace(/([ 0-9]+)([a-zA-Z])/g, function(a,b,c) {
+ return b.trim()+c.toUpperCase();
+ });
+ return str;
+}
- /**
- * Returns the value for a given column
- * @param {col}
- * @return {value}
- */
- getValue(col){
- if(!col.prop) return '';
- return DeepValueGetter(this.row, col.prop);
- }
- /**
- * Invoked when a cell triggers the tree toggle
- * @param {cell}
- */
- onTreeToggled(cell){
- this.onTreeToggle({
- cell: cell,
- row: this.row
- });
- }
-
- /**
- * Calculates the styles for a pin group
- * @param {group}
- * @return {styles object}
- */
- stylesByGroup( group){
- var styles = {
- width: this.columnWidths[group] + 'px'
- };
+/**
+ * Gets the width of the scrollbar. Nesc for windows
+ * http://stackoverflow.com/a/13382873/888165
+ * @return {int} width
+ */
+function ScrollbarWidth() {
+ var outer = document.createElement("div");
+ outer.style.visibility = "hidden";
+ outer.style.width = "100px";
+ outer.style.msOverflowStyle = "scrollbar";
+ document.body.appendChild(outer);
- if(group === 'left'){
- TranslateXY(styles, this.options.internal.offsetX, 0);
- } else if(group === 'right'){
- var offset = (((this.columnWidths.total - this.options.internal.innerWidth) -
- this.options.internal.offsetX) + this.options.internal.scrollBarWidth) * -1;
- TranslateXY(styles, offset, 0);
- }
+ var widthNoScroll = outer.offsetWidth;
+ outer.style.overflow = "scroll";
- return styles;
- }
+ var inner = document.createElement("div");
+ inner.style.width = "100%";
+ outer.appendChild(inner);
- /**
- * Invoked when the cell directive's checkbox changed state
- */
- onCheckboxChanged(ev){
- this.onCheckboxChange({
- $event: ev,
- row: this.row
- });
- }
+ var widthWithScroll = inner.offsetWidth;
+ outer.parentNode.removeChild(outer);
+ return widthNoScroll - widthWithScroll;
}
-function RowDirective(){
- return {
- restrict: 'E',
- controller: RowController,
- controllerAs: 'rowCtrl',
- scope: true,
- bindToController: {
- row: '=',
- columns: '=',
- columnWidths: '=',
- expanded: '=',
- selected: '=',
- hasChildren: '=',
- options: '=',
- onCheckboxChange: '&',
- onTreeToggle: '&'
- },
- link: function($scope, $elm, $attrs, ctrl){
- if(ctrl.row){
- // inital render position
- TranslateXY($elm[0].style, 0, ctrl.row.$$index * ctrl.options.rowHeight);
- }
-
- // register w/ the style translator
- ctrl.options.internal.styleTranslator.register($scope.$index, $elm);
- },
- template: `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
`,
- replace:true
- };
+function NextSortDirection(sortType, currentSort) {
+ if (sortType === 'single') {
+ if(currentSort === 'asc'){
+ return 'desc';
+ } else {
+ return 'asc';
+ }
+ } else {
+ if(!currentSort){
+ return 'asc';
+ } else if(currentSort === 'asc'){
+ return 'desc';
+ } else if(currentSort === 'desc'){
+ return undefined;
+ }
+ }
}
-
/**
- * Shortcut for key handlers
- * @type {Object}
+ * Calculates the total width of all columns and their groups
+ * @param {array} columns
+ * @param {string} property width to get
*/
-var KEYS = {
- BACKSPACE: 8,
- TAB: 9,
- RETURN: 13,
- ALT: 18,
- ESC: 27,
- SPACE: 32,
- PAGE_UP: 33,
- PAGE_DOWN: 34,
- END: 35,
- HOME: 36,
- LEFT: 37,
- UP: 38,
- RIGHT: 39,
- DOWN: 40,
- DELETE: 46,
- COMMA: 188,
- PERIOD: 190,
- A: 65,
- Z: 90,
- ZERO: 48,
- NUMPAD_0: 96,
- NUMPAD_9: 105
-};
+function ColumnTotalWidth(columns, prop) {
+ var totalWidth = 0;
-class SelectionController {
+ columns.forEach((c) => {
+ var has = prop && c[prop];
+ totalWidth = totalWidth + (has ? c[prop] : c.width);
+ });
- /*@ngInject*/
- constructor($scope){
- this.body = $scope.body;
- this.options = $scope.body.options;
- this.selected = $scope.body.selected;
- }
+ return totalWidth;
+}
- /**
- * Handler for the keydown on a row
- * @param {event}
- * @param {index}
- * @param {row}
- */
- keyDown(ev, index, row){
- if(KEYS[ev.keyCode]){
- ev.preventDefault();
- }
+/**
+ * Calculates the Total Flex Grow
+ * @param {array}
+ */
+function GetTotalFlexGrow(columns){
+ var totalFlexGrow = 0;
- if (ev.keyCode === KEYS.DOWN) {
- var next = ev.target.nextElementSibling;
- if(next){
- next.focus();
- }
- } else if (ev.keyCode === KEYS.UP) {
- var prev = ev.target.previousElementSibling;
- if(prev){
- prev.focus();
- }
- } else if(ev.keyCode === KEYS.RETURN){
- this.selectRow(index, row);
- }
+ for (let c of columns) {
+ totalFlexGrow += c.flexGrow || 0;
}
- /**
- * Handler for the row click event
- * @param {object} event
- * @param {int} index
- * @param {object} row
- */
- rowClicked(event, index, row){
- if(!this.options.checkboxSelection){
- // event.preventDefault();
- this.selectRow(event, index, row);
- }
+ return totalFlexGrow;
+}
- this.body.onRowClick({ row: row });
- }
-
- /**
- * Handler for the row double click event
- * @param {object} event
- * @param {int} index
- * @param {object} row
- */
- rowDblClicked(event, index, row){
- if(!this.options.checkboxSelection){
- event.preventDefault();
- this.selectRow(event, index, row);
- }
+/**
+ * Adjusts the column widths.
+ * Inspired by: https://github.com/facebook/fixed-data-table/blob/master/src/FixedDataTableWidthHelper.js
+ * @param {array} all columns
+ * @param {int} width
+ */
+function AdjustColumnWidths(allColumns, expectedWidth){
+ var columnsWidth = ColumnTotalWidth(allColumns),
+ totalFlexGrow = GetTotalFlexGrow(allColumns),
+ colsByGroup = ColumnsByPin(allColumns);
- this.body.onRowDblClick({ row: row });
+ if (columnsWidth !== expectedWidth){
+ ScaleColumns(colsByGroup, expectedWidth, totalFlexGrow);
}
+}
- /**
- * Invoked when a row directive's checkbox was changed.
- * @param {index}
- * @param {row}
- */
- onCheckboxChange(event, index, row){
- this.selectRow(event, index, row);
- }
+/**
+ * Resizes columns based on the flexGrow property, while respecting manually set widths
+ * @param {array} colsByGroup
+ * @param {int} maxWidth
+ * @param {int} totalFlexGrow
+ */
+function ScaleColumns(colsByGroup, maxWidth, totalFlexGrow) {
+ // calculate total width and flexgrow points for coulumns that can be resized
+ angular$1.forEach(colsByGroup, (cols) => {
+ cols.forEach((column) => {
+ if (!column.canAutoResize){
+ maxWidth -= column.width;
+ totalFlexGrow -= column.flexGrow;
+ } else {
+ column.width = 0;
+ }
+ });
+ });
- /**
- * Selects a row and places in the selection collection
- * @param {index}
- * @param {row}
- */
- selectRow(event, index, row){
- if(this.options.selectable){
- if(this.options.multiSelect){
- var isCtrlKeyDown = event.ctrlKey || event.metaKey,
- isShiftKeyDown = event.shiftKey;
+ var hasMinWidth = {};
+ var remainingWidth = maxWidth;
- if(isShiftKeyDown){
- this.selectRowsBetween(index, row);
- } else {
- var idx = this.selected.indexOf(row);
- if(idx > -1){
- this.selected.splice(idx, 1);
+ // resize columns until no width is left to be distributed
+ do {
+ let widthPerFlexPoint = remainingWidth / totalFlexGrow;
+ remainingWidth = 0;
+ angular$1.forEach(colsByGroup, (cols) => {
+ cols.forEach((column, i) => {
+ // if the column can be resize and it hasn't reached its minimum width yet
+ if (column.canAutoResize && !hasMinWidth[i]){
+ let newWidth = column.width + column.flexGrow * widthPerFlexPoint;
+ if (column.minWidth !== undefined && newWidth < column.minWidth){
+ remainingWidth += newWidth - column.minWidth;
+ column.width = column.minWidth;
+ hasMinWidth[i] = true;
} else {
- if(this.options.multiSelectOnShift && this.selected.length === 1) {
- this.selected.splice(0, 1);
- }
- this.selected.push(row);
- this.body.onSelect({ rows: [ row ] });
+ column.width = newWidth;
}
}
- this.prevIndex = index;
+ });
+ });
+ } while (remainingWidth !== 0);
+
+}
+
+/**
+ * Forces the width of the columns to
+ * distribute equally but overflowing when nesc.
+ *
+ * Rules:
+ *
+ * - If combined withs are less than the total width of the grid,
+ * proporation the widths given the min / max / noraml widths to fill the width.
+ *
+ * - If the combined widths, exceed the total width of the grid,
+ * use the standard widths.
+ *
+ * - If a column is resized, it should always use that width
+ *
+ * - The proporational widths should never fall below min size if specified.
+ *
+ * - If the grid starts off small but then becomes greater than the size ( + / - )
+ * the width should use the orginial width; not the newly proporatied widths.
+ *
+ * @param {array} allColumns
+ * @param {int} expectedWidth
+ */
+function ForceFillColumnWidths(allColumns, expectedWidth, startIdx){
+ var contentWidth = 0,
+ columnsToResize = startIdx > -1 ?
+ allColumns.slice(startIdx, allColumns.length).filter((c) => { return c.canAutoResize }) :
+ allColumns.filter((c) => { return c.canAutoResize });
+
+ allColumns.forEach((c) => {
+ if(!c.canAutoResize){
+ contentWidth += c.width;
+ } else {
+ contentWidth += (c.$$oldWidth || c.width);
+ }
+ });
+
+ var remainingWidth = expectedWidth - contentWidth,
+ additionWidthPerColumn = remainingWidth / columnsToResize.length,
+ exceedsWindow = contentWidth > expectedWidth;
+
+ columnsToResize.forEach((column) => {
+ if(exceedsWindow){
+ column.width = column.$$oldWidth || column.width;
+ } else {
+ if(!column.$$oldWidth){
+ column.$$oldWidth = column.width;
+ }
+
+ var newSize = column.$$oldWidth + additionWidthPerColumn;
+ if(column.minWith && newSize < column.minWidth){
+ column.width = column.minWidth;
+ } else if(column.maxWidth && newSize > column.maxWidth){
+ column.width = column.maxWidth;
} else {
- this.selected = row;
- this.body.onSelect({ rows: [ row ] });
+ column.width = newSize;
}
}
- }
+ });
+}
+
+class DataTableController {
/**
- * Selects the rows between a index. Used for shift click selection.
- * @param {index}
+ * Creates an instance of the DataTable Controller
+ * @param {scope}
+ * @param {filter}
*/
- selectRowsBetween(index){
- var reverse = index < this.prevIndex,
- selecteds = [];
+ /*@ngInject*/
+ constructor($scope, $filter, $log, $transclude){
+ Object.assign(this, {
+ $scope: $scope,
+ $filter: $filter,
+ $log: $log
+ });
- for(var i=0, len=this.body.rows.length; i < len; i++) {
- var row = this.body.rows[i],
- greater = i >= this.prevIndex && i <= index,
- lesser = i <= this.prevIndex && i >= index;
+ this.defaults();
- var range = {};
- if ( reverse ) {
- range = {
- start: index,
- end: ( this.prevIndex - index )
- }
- } else {
- range = {
- start: this.prevIndex,
- end: index + 1
- }
- }
+ // set scope to the parent
+ this.options.$outer = $scope.$parent;
- if((reverse && lesser) || (!reverse && greater)){
- var idx = this.selected.indexOf(row);
- // if reverse shift selection (unselect) and the
- // row is already selected, remove it from selected
- if ( reverse && idx > -1 ) {
- this.selected.splice(idx, 1);
- continue;
- }
- // if in the positive range to be added to `selected`, and
- // not already in the selected array, add it
- if( i >= range.start && i < range.end ){
- if ( idx === -1 ) {
- this.selected.push(row);
- selecteds.push(row);
- }
- }
- }
- }
+ $scope.$watch('dt.options.columns', (newVal, oldVal) => {
+ this.transposeColumnDefaults();
- this.body.onSelect({ rows: selecteds });
- }
-}
+ if(newVal.length !== oldVal.length){
+ this.adjustColumns();
+ }
-function SelectionDirective(){
- return {
- controller: SelectionController,
- restrict: 'A',
- require:'^dtBody',
- controllerAs: 'selCtrl'
- };
-}
+ this.calculateColumns();
+ }, true);
+ // default sort
+ var watch = $scope.$watch('dt.rows', (newVal) => {
+ if(newVal){
+ watch();
+ this.onSorted();
+ }
+ });
+ }
-/**
- * Shim layer with setTimeout fallback
- * http://www.html5rocks.com/en/tutorials/speed/animations/
- */
-var requestAnimFrame = (function(){
- return window.requestAnimationFrame ||
- window.webkitRequestAnimationFrame ||
- window.mozRequestAnimationFrame ||
- window.oRequestAnimationFrame ||
- window.msRequestAnimationFrame ||
- function( callback ){
- window.setTimeout(callback, 1000 / 60);
- };
-})();
+ /**
+ * Creates and extends default options for the grid control
+ */
+ defaults(){
+ this.expanded = this.expanded || {};
+ this.options = angular$1.extend(angular$1.
+ copy(TableDefaults), this.options);
-/**
- * This translates the dom position based on the model row index.
- * This only exists because Angular's binding process is too slow.
- */
-class StyleTranslator{
+ angular$1.forEach(TableDefaults.paging, (v,k) => {
+ if(!this.options.paging[k]){
+ this.options.paging[k] = v;
+ }
+ });
- constructor(height){
- this.height = height;
- this.map = new Map();
+ if(this.options.selectable && this.options.multiSelect){
+ this.selected = this.selected || [];
+ }
}
/**
- * Update the rows
- * @param {Array} rows
+ * On init or when a column is added, we need to
+ * make sure all the columns added have the correct
+ * defaults applied.
*/
- update(rows){
- let n = 0;
- while (n <= this.map.size) {
- let dom = this.map.get(n);
- let model = rows[n];
- if(dom && model){
- TranslateXY(dom[0].style, 0, model.$$index * this.height);
+ transposeColumnDefaults(){
+ for(var i=0, len = this.options.columns.length; i < len; i++) {
+ var column = this.options.columns[i];
+ column.$id = ObjectId();
+
+ angular$1.forEach(ColumnDefaults, (v,k) => {
+ if(!column.hasOwnProperty(k)){
+ column[k] = v;
+ }
+ });
+
+ if(column.name && !column.prop){
+ column.prop = CamelCase(column.name);
}
- n++;
+
+ this.options.columns[i] = column;
}
}
/**
- * Register the row
- * @param {int} idx
- * @param {dom} dom
+ * Calculate column groups and widths
*/
- register(idx, dom){
- this.map.set(idx, dom);
+ calculateColumns(){
+ var columns = this.options.columns;
+ this.columnsByPin = ColumnsByPin(columns);
+ this.columnWidths = ColumnGroupWidths(this.columnsByPin, columns);
}
-}
-
-function ScrollerDirective($timeout, $rootScope){
- return {
- restrict: 'E',
- require:'^dtBody',
- transclude: true,
- replace: true,
- template: `
`,
- link: function($scope, $elm, $attrs, ctrl){
- var ticking = false,
- lastScrollY = 0,
- lastScrollX = 0,
- parent = $elm.parent();
-
- ctrl.options.internal.styleTranslator =
- new StyleTranslator(ctrl.options.rowHeight);
-
- ctrl.options.internal.setYOffset = function(offsetY){
- parent[0].scrollTop = offsetY;
- };
+ /**
+ * Returns the css classes for the data table.
+ * @return {style object}
+ */
+ tableCss(){
+ return {
+ 'fixed': this.options.scrollbarV,
+ 'selectable': this.options.selectable,
+ 'checkboxable': this.options.checkboxSelection
+ };
+ }
- function update(){
- ctrl.options.internal.offsetY = lastScrollY;
- ctrl.options.internal.offsetX = lastScrollX;
- ctrl.updatePage();
+ /**
+ * Adjusts the column widths to handle greed/etc.
+ * @param {int} forceIdx
+ */
+ adjustColumns(forceIdx){
+ var width = this.options.internal.innerWidth - this.options.internal.scrollBarWidth;
- if(ctrl.options.scrollbarV){
- ctrl.getRows();
- }
+ if(this.options.columnMode === 'force'){
+ ForceFillColumnWidths(this.options.columns, width, forceIdx);
+ } else if(this.options.columnMode === 'flex') {
+ AdjustColumnWidths(this.options.columns, width);
+ }
+ }
- // https://github.com/Swimlane/angular-data-table/pull/74
- ctrl.options.$outer.$digest();
+ /**
+ * Calculates the page size given the height * row height.
+ * @return {[type]}
+ */
+ calculatePageSize(){
+ this.options.paging.size = Math.ceil(
+ this.options.internal.bodyHeight / this.options.rowHeight) + 1;
+ }
- ticking = false;
- };
+ /**
+ * Sorts the values of the grid for client side sorting.
+ */
+ onSorted(){
+ if(!this.rows) return;
- function requestTick() {
- if(!ticking) {
- requestAnimFrame(update);
- ticking = true;
+ // return all sorted column, in the same order in which they were sorted
+ var sorts = this.options.columns
+ .filter((c) => {
+ return c.sort;
+ })
+ .sort((a, b) => {
+ // sort the columns with lower sortPriority order first
+ if (a.sortPriority && b.sortPriority){
+ if (a.sortPriority > b.sortPriority) return 1;
+ if (a.sortPriority < b.sortPriority) return -1;
+ } else if (a.sortPriority){
+ return -1;
+ } else if (b.sortPriority){
+ return 1;
}
- };
- parent.on('scroll', function(ev) {
- lastScrollY = this.scrollTop;
- lastScrollX = this.scrollLeft;
- requestTick();
+ return 0;
+ })
+ .map((c, i) => {
+ // update sortPriority
+ c.sortPriority = i + 1;
+ return c;
});
- $scope.$on('$destroy', () => {
- parent.off('scroll');
- });
+ if(sorts.length){
+ this.onSort({sorts: sorts});
- $scope.scrollerStyles = function(){
- if(ctrl.options.scrollbarV){
- return {
- height: ctrl.count * ctrl.options.rowHeight + 'px'
+ if (this.options.onSort){
+ this.options.onSort(sorts);
+ }
+
+ var clientSorts = [];
+ for(var i=0, len=sorts.length; i < len; i++) {
+ var c = sorts[i];
+ if(c.comparator !== false){
+ var dir = c.sort === 'asc' ? '' : '-';
+ if (c.sortBy !== undefined) {
+ clientSorts.push(dir + c.sortBy);
+ } else {
+ clientSorts.push(dir + c.prop);
}
}
- };
+ }
+ if(clientSorts.length){
+ // todo: more ideal to just resort vs splice and repush
+ // but wasn't responding to this change ...
+ var sortedValues = this.$filter('orderBy')(this.rows, clientSorts);
+ this.rows.splice(0, this.rows.length);
+ this.rows.push(...sortedValues);
+ }
}
- };
-}
-class BodyController{
+ this.options.internal.setYOffset(0);
+ }
/**
- * A tale body controller
- * @param {$scope}
- * @param {$timeout}
- * @return {BodyController}
+ * Invoked when a tree is collasped/expanded
+ * @param {row model}
+ * @param {cell model}
*/
- /*@ngInject*/
- constructor($scope, $timeout){
- this.$scope = $scope;
- this.tempRows = [];
-
- this.treeColumn = this.options.columns.find((c) => {
- return c.isTreeColumn;
+ onTreeToggled(row, cell){
+ this.onTreeToggle({
+ row: row,
+ cell: cell
});
+ }
- this.groupColumn = this.options.columns.find((c) => {
- return c.group;
+ /**
+ * Invoked when the body triggers a page change.
+ * @param {offset}
+ * @param {size}
+ */
+ onBodyPage(offset, size){
+ this.onPage({
+ offset: offset,
+ size: size
});
-
- $scope.$watchCollection('body.rows', this.rowsUpdated.bind(this));
-
- if(this.options.scrollbarV || (!this.options.scrollbarV && this.options.paging.externalPaging)){
- var sized = false;
- $scope.$watch('body.options.paging.size', (newVal, oldVal) => {
- if(!sized || newVal > oldVal){
- this.getRows();
- sized = true;
- }
- });
-
- $scope.$watch('body.options.paging.count', (count) => {
- this.count = count;
- this.updatePage();
- });
-
- $scope.$watch('body.options.paging.offset', (newVal) => {
- if(this.options.paging.size){
- this.onPage({
- offset: newVal,
- size: this.options.paging.size
- });
- }
- });
- }
}
- rowsUpdated(newVal, oldVal){
- if(newVal) {
- if(!this.options.paging.externalPaging){
- this.options.paging.count = newVal.length;
- }
+ /**
+ * Invoked when the footer triggers a page change.
+ * @param {offset}
+ * @param {size}
+ */
+ onFooterPage(offset, size){
+ var pageBlockSize = this.options.rowHeight * size,
+ offsetY = pageBlockSize * offset;
+
+ this.options.internal.setYOffset(offsetY);
+ }
- this.count = this.options.paging.count;
+ /**
+ * Invoked when the header checkbox directive has changed.
+ */
+ onHeaderCheckboxChange(){
+ if(this.rows){
+ var matches = this.selected.length === this.rows.length;
+ this.selected.splice(0, this.selected.length);
- if(this.treeColumn || this.groupColumn){
- this.buildRowsByGroup();
+ if(!matches){
+ this.selected.push(...this.rows);
}
+ }
+ }
- if(this.options.scrollbarV){
- let refresh = newVal && oldVal && (newVal.length === oldVal.length
- || newVal.length < oldVal.length);
-
- this.getRows(refresh);
- } else {
- let rows = this.rows;
+ /**
+ * Returns if all the rows are selected
+ * @return {Boolean} if all selected
+ */
+ isAllRowsSelected(){
+ if(this.rows) return false;
+ return this.selected.length === this.rows.length;
+ }
- if(this.treeColumn){
- rows = this.buildTree();
- } else if(this.groupColumn){
- rows = this.buildGroups();
- }
+ /**
+ * Occurs when a header directive triggered a resize event
+ * @param {object} column
+ * @param {int} width
+ */
+ onResized(column, width){
+ var idx =this.options.columns.indexOf(column);
+ if(idx > -1){
+ var column = this.options.columns[idx];
+ column.width = width;
+ column.canAutoResize = false;
- if(this.options.paging.externalPaging){
- let idxs = this.getFirstLastIndexes(),
- idx = idxs.first;
+ this.adjustColumns(idx);
+ this.calculateColumns();
+ }
- this.tempRows.splice(0, this.tempRows.length);
- while(idx < idxs.last){
- this.tempRows.push(rows[idx++])
- }
- } else {
- this.tempRows.splice(0, this.tempRows.length);
- this.tempRows.push(...rows);
- }
- }
+ if (this.onColumnResize){
+ this.onColumnResize({
+ column: column,
+ width: width
+ });
}
}
/**
- * Gets the first and last indexes based on the offset, row height, page size, and overall count.
+ * Occurs when a row was selected
+ * @param {object} rows
*/
- getFirstLastIndexes(){
- var firstRowIndex, endIndex;
-
- if(this.options.scrollbarV){
- firstRowIndex = Math.max(Math.floor((
- this.options.internal.offsetY || 0) / this.options.rowHeight, 0), 0);
- endIndex = Math.min(firstRowIndex + this.options.paging.size, this.count);
- } else {
- if(this.options.paging.externalPaging){
- firstRowIndex = Math.max(this.options.paging.offset * this.options.paging.size, 0);
- endIndex = Math.min(firstRowIndex + this.options.paging.size, this.count);
- } else {
- endIndex = this.count;
- }
- }
+ onSelected(rows){
+ this.onSelect({
+ rows: rows
+ });
+ }
- return {
- first: firstRowIndex,
- last: endIndex
- };
+ /**
+ * Occurs when a row was click but may not be selected.
+ * @param {object} row
+ */
+ onRowClicked(row){
+ this.onRowClick({
+ row: row
+ });
}
/**
- * Updates the page's offset given the scroll position.
+ * Occurs when a row was double click but may not be selected.
+ * @param {object} row
*/
- updatePage(){
- let curPage = this.options.paging.offset,
- idxs = this.getFirstLastIndexes();
+ onRowDblClicked(row){
+ this.onRowDblClick({
+ row: row
+ });
+ }
- if (this.options.internal.oldScrollPosition === undefined){
- this.options.internal.oldScrollPosition = 0;
- }
+}
- let oldScrollPosition = this.options.internal.oldScrollPosition,
- newPage = idxs.first / this.options.paging.size;
+/**
+ * Debounce helper
+ * @param {function}
+ * @param {int}
+ * @param {boolean}
+ */
- this.options.internal.oldScrollPosition = newPage;
- if (newPage < oldScrollPosition) {
- // scrolling up
- newPage = Math.floor(newPage);
- } else if (newPage > oldScrollPosition){
- // scrolling down
- newPage = Math.ceil(newPage);
- } else {
- // equal, just stay on the current page
- newPage = curPage;
+/**
+ * Throttle helper
+ * @param {function}
+ * @param {boolean}
+ * @param {object}
+ */
+function throttle(func, wait, options) {
+ var context, args, result;
+ var timeout = null;
+ var previous = 0;
+ options || (options = {});
+ var later = function() {
+ previous = options.leading === false ? 0 : new Date();
+ timeout = null;
+ result = func.apply(context, args);
+ };
+ return function() {
+ var now = new Date();
+ if (!previous && options.leading === false)
+ previous = now;
+ var remaining = wait - (now - previous);
+ context = this;
+ args = arguments;
+ if (remaining <= 0) {
+ clearTimeout(timeout);
+ timeout = null;
+ previous = now;
+ result = func.apply(context, args);
+ } else if (!timeout && options.trailing !== false) {
+ timeout = setTimeout(later, remaining);
}
+ return result;
+ };
+}
- if(!isNaN(newPage)){
- this.options.paging.offset = newPage;
- }
- }
+let DataTableService = {
- /**
- * Recursively calculate row depth for unsorted backend data
- * @param row
- * @param depth
- * @return {Integer}
- */
- calculateDepth(row, depth=0){
- var parentProp = this.treeColumn ? this.treeColumn.relationProp : this.groupColumn.prop;
- var prop = this.treeColumn.prop;
- if (!row[parentProp]){
- return depth;
- }
- if (row.$$depth) {
- return row.$$depth + depth;
- }
- /* Get data from cache, if exists*/
- var cachedParent = this.index[row[parentProp]];
- if (cachedParent) {
- depth += 1;
- return this.calculateDepth(cachedParent, depth);
- }
- for (var i=0, len = this.rows.length; i < len; i++){
- var parent = this.rows[i];
- if (parent[prop] == row[parentProp]){
- depth+=1;
- return this.calculateDepth(parent, depth);
- }
+ // id: [ column defs ]
+ columns: {},
+ dTables: {},
+
+ saveColumns(id, columnElms) {
+ if (columnElms && columnElms.length) {
+ let columnsArray = [].slice.call(columnElms);
+ this.dTables[id] = columnsArray;
}
- return depth;
- }
+ },
/**
- * Matches groups to their respective parents by index.
- *
- * Example:
- *
- * {
- * "Acme" : [
- * { name: "Acme Holdings", parent: "Acme" }
- * ],
- * "Acme Holdings": [
- * { name: "Acme Ltd", parent: "Acme Holdings" }
- * ]
- * }
- *
+ * Create columns from elements
+ * @param {array} columnElms
*/
- buildRowsByGroup(){
- this.index = {};
- this.rowsByGroup = {};
+ buildColumns(scope, parse) {
+ //FIXME: Too many nested for loops. O(n3)
+
+ // Iterate through each dTable
+ angular$1.forEach(this.dTables, (columnElms, id) => {
+ this.columns[id] = [];
+
+ // Iterate through each column
+ angular$1.forEach(columnElms, (c) => {
+ let column = {};
+
+ var visible = true;
+ // Iterate through each attribute
+ angular$1.forEach(c.attributes, (attr) => {
+ let attrName = CamelCase(attr.name);
+
+ // cuz putting className vs class on
+ // a element feels weird
+ switch (attrName) {
+ case 'class':
+ column.className = attr.value;
+ break;
+ case 'name':
+ case 'prop':
+ column[attrName] = attr.value;
+ break;
+ case 'headerRenderer':
+ case 'cellRenderer':
+ case 'cellDataGetter':
+ column[attrName] = parse(attr.value);
+ break;
+ case 'visible':
+ visible = parse(attr.value)(scope);
+ break;
+ default:
+ column[attrName] = parse(attr.value)(scope);
+ break;
+ }
+ });
- var parentProp = this.treeColumn ?
- this.treeColumn.relationProp :
- this.groupColumn.prop;
+ let header = c.getElementsByTagName('column-header');
+ if(header.length){
+ column.headerTemplate = header[0].innerHTML;
+ c.removeChild(header[0]);
+ }
- for(var i = 0, len = this.rows.length; i < len; i++) {
- var row = this.rows[i];
- // build groups
- var relVal = row[parentProp];
- if(relVal){
- if(this.rowsByGroup[relVal]){
- this.rowsByGroup[relVal].push(row);
- } else {
- this.rowsByGroup[relVal] = [ row ];
+ if (c.innerHTML !== '') {
+ column.template = c.innerHTML;
}
- }
- // build indexes
- if(this.treeColumn){
- var prop = this.treeColumn.prop;
- this.index[row[prop]] = row;
+ if (visible)
+ this.columns[id].push(column);
+ });
+ });
- if (row[parentProp] === undefined){
- row.$$depth = 0;
- } else {
- var parent = this.index[row[parentProp]];
- if (parent === undefined){
- for (var j=0; j < len; j++){
- if (this.rows[j][prop] == relVal){
- parent = this.rows[j];
- break;
- }
- }
- }
- if (parent.$$depth === undefined) {
- parent.$$depth = this.calculateDepth(parent);
- }
- row.$$depth = parent.$$depth + 1;
- if (parent.$$children){
- parent.$$children.push(row[prop]);
- } else {
- parent.$$children = [row[prop]];
- }
- }
- }
- }
+ this.dTables = {};
}
+};
- /**
- * Rebuilds the groups based on what is expanded.
- * This function needs some optimization, todo for future release.
- * @return {Array} the temp array containing expanded rows
- */
- buildGroups(){
- var temp = [];
+function DataTableDirective($window, $timeout, $parse){
+ return {
+ restrict: 'E',
+ replace: true,
+ controller: DataTableController,
+ scope: true,
+ bindToController: {
+ options: '=',
+ rows: '=',
+ selected: '=?',
+ expanded: '=?',
+ onSelect: '&',
+ onSort: '&',
+ onTreeToggle: '&',
+ onPage: '&',
+ onRowClick: '&',
+ onRowDblClick: '&',
+ onColumnResize: '&'
+ },
+ controllerAs: 'dt',
+ template: function(element){
+ // Gets the column nodes to transposes to column objects
+ // http://stackoverflow.com/questions/30845397/angular-expressive-directive-design/30847609#30847609
+ var columns = element[0].getElementsByTagName('column'),
+ id = ObjectId();
+ DataTableService.saveColumns(id, columns);
- angular.forEach(this.rowsByGroup, (v, k) => {
- temp.push({
- name: k,
- group: true
- });
+ return `
+
+
+
+
+
+
+
`
+ },
+ compile: function(tElem, tAttrs){
+ return {
+ pre: function($scope, $elm, $attrs, ctrl){
+ DataTableService.buildColumns($scope, $parse);
- if(this.expanded[k]){
- temp.push(...v);
- }
- });
+ // Check and see if we had expressive columns
+ // and if so, lets use those
+ var id = $elm.attr('data-column-id'),
+ columns = DataTableService.columns[id];
+ if (columns) {
+ ctrl.options.columns = columns;
+ }
- return temp;
- }
+ ctrl.transposeColumnDefaults();
+ ctrl.options.internal.scrollBarWidth = ScrollbarWidth();
- /**
- * Returns if the row is selected
- * @param {row}
- * @return {Boolean}
- */
- isSelected(row){
- var selected = false;
+ /**
+ * Invoked on init of control or when the window is resized;
+ */
+ function resize() {
+ var rect = $elm[0].getBoundingClientRect();
- if(this.options.selectable){
- if(this.options.multiSelect){
- selected = this.selected.indexOf(row) > -1;
- } else {
- selected = this.selected === row;
- }
- }
+ ctrl.options.internal.innerWidth = Math.floor(rect.width);
- return selected;
- }
+ if (ctrl.options.scrollbarV) {
+ var height = rect.height;
- /**
- * Creates a tree of the existing expanded values
- * @return {array} the built tree
- */
- buildTree(){
- var temp = [],
- self = this;
+ if (ctrl.options.headerHeight) {
+ height = height - ctrl.options.headerHeight;
+ }
- function addChildren(fromArray, toArray, level) {
- fromArray.forEach(function (row) {
- var relVal = row[self.treeColumn.relationProp],
- key = row[self.treeColumn.prop],
- groupRows = self.rowsByGroup[key],
- expanded = self.expanded[key];
+ if (ctrl.options.footerHeight) {
+ height = height - ctrl.options.footerHeight;
+ }
- if (level > 0 || !relVal) {
- toArray.push(row);
- if (groupRows && groupRows.length > 0 && expanded) {
- addChildren(groupRows, toArray, level + 1);
+ ctrl.options.internal.bodyHeight = height;
+ ctrl.calculatePageSize();
+ }
+
+ ctrl.adjustColumns();
}
+
+ $window.addEventListener('resize',
+ throttle(() => {
+ $timeout(resize);
+ }));
+
+ // When an item is hidden for example
+ // in a tab with display none, the height
+ // is not calculated correrctly. We need to watch
+ // the visible attribute and resize if this occurs
+ var checkVisibility = function() {
+ var bounds = $elm[0].getBoundingClientRect(),
+ visible = bounds.width && bounds.height;
+ if (visible) resize();
+ else $timeout(checkVisibility, 100);
+ };
+ checkVisibility();
+
+ // add a loaded class to avoid flickering
+ $elm.addClass('dt-loaded');
+
+ // prevent memory leaks
+ $scope.$on('$destroy', () => {
+ angular$1.element($window).off('resize');
+ });
}
+ };
+ }
+ };
+}
- });
+var cache = {};
+var testStyle = document.createElement('div').style;
+
+// Get Prefix
+// http://davidwalsh.name/vendor-prefix
+var prefix = (function () {
+ var styles = window.getComputedStyle(document.documentElement, ''),
+ pre = (Array.prototype.slice
+ .call(styles)
+ .join('')
+ .match(/-(moz|webkit|ms)-/) || (styles.OLink === '' && ['', 'o'])
+ )[1],
+ dom = ('WebKit|Moz|MS|O').match(new RegExp('(' + pre + ')', 'i'))[1];
+ return {
+ dom: dom,
+ lowercase: pre,
+ css: '-' + pre + '-',
+ js: pre[0].toUpperCase() + pre.substr(1)
+ };
+})();
+
+/**
+ * @param {string} property Name of a css property to check for.
+ * @return {?string} property name supported in the browser, or null if not
+ * supported.
+ */
+function GetVendorPrefixedName(property) {
+ var name = CamelCase(property);
+ if(!cache[name]){
+ if(testStyle[prefix.css + property] !== undefined) {
+ cache[name] = prefix.css + property;
+ } else if(testStyle[property] !== undefined){
+ cache[name] = property;
}
-
- addChildren(this.rows, temp, 0);
-
- return temp;
}
+ return cache[name];
+}
- /**
- * Creates the intermediate collection that is shown in the view.
- * @param {boolean} refresh - bust the tree/group cache
- */
- getRows(refresh){
- // only proceed when we have pre-aggregated the values
- if((this.treeColumn || this.groupColumn) && !this.rowsByGroup){
- return false;
- }
-
- var temp;
-
- if(this.treeColumn) {
- temp = this.treeTemp || [];
- // cache the tree build
- if((refresh || !this.treeTemp)){
- this.treeTemp = temp = this.buildTree();
- this.count = temp.length;
+// browser detection and prefixing tools
+var transform = GetVendorPrefixedName('transform');
+var backfaceVisibility = GetVendorPrefixedName('backfaceVisibility');
+var hasCSSTransforms = !!GetVendorPrefixedName('transform');
+var hasCSS3DTransforms = !!GetVendorPrefixedName('perspective');
+var ua = window.navigator.userAgent;
+var isSafari = (/Safari\//).test(ua) && !(/Chrome\//).test(ua);
- // have to force reset, optimize this later
- this.tempRows.splice(0, this.tempRows.length);
- }
- } else if(this.groupColumn) {
- temp = this.groupsTemp || [];
- // cache the group build
- if((refresh || !this.groupsTemp)){
- this.groupsTemp = temp = this.buildGroups();
- this.count = temp.length;
- }
+function TranslateXY(styles, x,y){
+ if (hasCSSTransforms) {
+ if (!isSafari && hasCSS3DTransforms) {
+ styles[transform] = `translate3d(${x}px, ${y}px, 0)`;
+ styles[backfaceVisibility] = 'hidden';
} else {
- temp = this.rows;
- if(refresh === true){
- this.tempRows.splice(0, this.tempRows.length);
- }
+ styles[CamelCase(transform)] = `translate(${x}px, ${y}px)`;
}
+ } else {
+ styles.top = y + 'px';
+ styles.left = x + 'px';
+ }
+}
- var idx = 0,
- indexes = this.getFirstLastIndexes(),
- rowIndex = indexes.first;
-
- // slice out the old rows so we don't have duplicates
- this.tempRows.splice(0, indexes.last - indexes.first);
+class HeaderController {
- while (rowIndex < indexes.last && rowIndex < this.count) {
- var row = temp[rowIndex];
- if(row){
- row.$$index = rowIndex;
- this.tempRows[idx] = row;
- }
- idx++;
- rowIndex++;
+ /**
+ * Returns the styles for the header directive.
+ * @param {object} scope
+ * @return {object} styles
+ */
+ styles() {
+ return {
+ width: this.options.internal.innerWidth + 'px',
+ height: this.options.headerHeight + 'px'
}
-
- this.options.internal.styleTranslator.update(this.tempRows);
-
- return this.tempRows;
}
/**
- * Returns the styles for the table body directive.
- * @return {object}
+ * Returns the inner styles for the header directive
+ * @param {object} scope
+ * @return {object} styles
*/
- styles(){
- var styles = {
- width: this.options.internal.innerWidth + 'px'
+ innerStyles(){
+ return {
+ width: this.columnWidths.total + 'px'
};
-
- if(!this.options.scrollbarV){
- styles.overflowY = 'hidden';
- } else if(this.options.scrollbarH === false){
- styles.overflowX = 'hidden';
- }
-
- if(this.options.scrollbarV){
- styles.height = this.options.internal.bodyHeight + 'px';
- }
-
- return styles;
}
/**
- * Returns the styles for the row diretive.
- * @param {row}
- * @return {styles object}
+ * Invoked when a column sort direction has changed
+ * @param {object} scope
+ * @param {object} column
*/
- rowStyles(row){
- let styles = {};
+ onSorted(sortedColumn){
+ if (this.options.sortType === 'single') {
+ // if sort type is single, then only one column can be sorted at once,
+ // so we set the sort to undefined for the other columns
+ function unsortColumn(column) {
+ if (column !== sortedColumn) {
+ column.sort = undefined;
+ }
+ }
- if(this.options.rowHeight === 'auto'){
- styles.height = this.options.rowHeight + 'px';
+ this.columns.left.forEach(unsortColumn);
+ this.columns.center.forEach(unsortColumn);
+ this.columns.right.forEach(unsortColumn);
}
- return styles;
- }
-
- /**
- * Builds the styles for the row group directive
- * @param {object} row
- * @return {object} styles
- */
- groupRowStyles(row){
- var styles = this.rowStyles(row);
- styles.width = this.columnWidths.total + 'px';
- return styles;
+ this.onSort({
+ column: sortedColumn
+ });
}
/**
- * Returns the css classes for the row directive.
- * @param {row}
- * @return {css class object}
+ * Returns the styles by group for the headers.
+ * @param {scope}
+ * @param {group}
+ * @return {styles object}
*/
- rowClasses(row){
+ stylesByGroup(group){
var styles = {
- 'selected': this.isSelected(row),
- 'dt-row-even': row && row.$$index%2 === 0,
- 'dt-row-odd': row && row.$$index%2 !== 0
+ width: this.columnWidths[group] + 'px'
};
- if(this.treeColumn){
- // if i am a child
- styles['dt-leaf'] = this.rowsByGroup[row[this.treeColumn.relationProp]];
- // if i have children
- styles['dt-has-leafs'] = this.rowsByGroup[row[this.treeColumn.prop]];
- // the depth
- styles['dt-depth-' + row.$$depth] = true;
+ if(group === 'center'){
+ TranslateXY(styles, this.options.internal.offsetX * -1, 0);
+ } else if(group === 'right'){
+ var offset = (this.columnWidths.total - this.options.internal.innerWidth) *-1;
+ TranslateXY(styles, offset, 0);
}
return styles;
}
/**
- * Returns the row model for the index in the view.
- * @param {index}
- * @return {row model}
+ * Invoked when the header cell directive's checkbox has changed.
+ * @param {scope}
*/
- getRowValue(idx){
- return this.tempRows[idx];
+ onCheckboxChanged(){
+ this.onCheckboxChange();
}
/**
- * Calculates if a row is expanded or collasped for tree grids.
- * @param {row}
- * @return {boolean}
+ * Occurs when a header cell directive triggered a resize
+ * @param {object} scope
+ * @param {object} column
+ * @param {int} width
*/
- getRowExpanded(row){
- if(this.treeColumn) {
- return this.expanded[row[this.treeColumn.prop]];
- } else if(this.groupColumn){
- return this.expanded[row.name];
- }
+ onResized(column, width){
+ this.onResize({
+ column: column,
+ width: width
+ });
}
- /**
- * Calculates if the row has children
- * @param {row}
- * @return {boolean}
- */
- getRowHasChildren(row){
- if(!this.treeColumn) return;
- var children = this.rowsByGroup[row[this.treeColumn.prop]];
- return children !== undefined || (children && !children.length);
- }
+}
+
+function HeaderDirective($timeout){
+ return {
+ restrict: 'E',
+ controller: HeaderController,
+ controllerAs: 'header',
+ scope: true,
+ bindToController: {
+ options: '=',
+ columns: '=',
+ columnWidths: '=',
+ onSort: '&',
+ onResize: '&',
+ onCheckboxChange: '&'
+ },
+ template: `
+ `,
+ replace:true,
+ link: function($scope, $elm, $attrs, ctrl){
+
+ $scope.columnsResorted = function(event, columnId){
+ var col = findColumnById(columnId),
+ parent = angular$1.element(event.currentTarget),
+ newIdx = -1;
- /**
- * Tree toggle event from a cell
- * @param {row model}
- * @param {cell model}
- */
- onTreeToggled(row, cell){
- var val = row[this.treeColumn.prop];
- this.expanded[val] = !this.expanded[val];
+ angular$1.forEach(parent.children(), (c, i) => {
+ if (columnId === angular$1.element(c).attr('data-id')) {
+ newIdx = i;
+ }
+ });
- if(this.options.scrollbarV){
- this.getRows(true);
- } else {
- var values = this.buildTree();
- this.tempRows.splice(0, this.tempRows.length);
- this.tempRows.push(...values);
- }
+ $timeout(() => {
+ angular$1.forEach(ctrl.columns, (group) => {
+ var idx = group.indexOf(col);
+ if(idx > -1){
- this.onTreeToggle({
- row: row,
- cell: cell
- });
- }
+ // this is tricky because we want to update the index
+ // in the orig columns array instead of the grouped one
+ var curColAtIdx = group[newIdx],
+ siblingIdx = ctrl.options.columns.indexOf(curColAtIdx),
+ curIdx = ctrl.options.columns.indexOf(col);
- /**
- * Invoked when the row group directive was expanded
- * @param {object} row
- */
- onGroupToggle(row){
- this.expanded[row.name] = !this.expanded[row.name];
+ ctrl.options.columns.splice(curIdx, 1);
+ ctrl.options.columns.splice(siblingIdx, 0, col);
- if(this.options.scrollbarV){
- this.getRows(true);
- } else {
- var values = this.buildGroups();
- this.tempRows.splice(0, this.tempRows.length);
- this.tempRows.push(...values);
- }
- }
-}
+ return false;
+ }
+ });
-function BodyDirective($timeout){
- return {
- restrict: 'E',
- controller: BodyController,
- controllerAs: 'body',
- bindToController: {
- columns: '=',
- columnWidths: '=',
- rows: '=',
- options: '=',
- selected: '=?',
- expanded: '=?',
- onPage: '&',
- onTreeToggle: '&',
- onSelect: '&',
- onRowClick: '&',
- onRowDblClick: '&'
- },
- scope: true,
- template: `
-
- `
- };
-}
+ });
+ };
-function NextSortDirection(sortType, currentSort) {
- if (sortType === 'single') {
- if(currentSort === 'asc'){
- return 'desc';
- } else {
- return 'asc';
- }
- } else {
- if(!currentSort){
- return 'asc';
- } else if(currentSort === 'asc'){
- return 'desc';
- } else if(currentSort === 'desc'){
- return undefined;
+ var findColumnById = function(columnId){
+ var columns = ctrl.columns.left.concat(ctrl.columns.center).concat(ctrl.columns.right);
+ return columns.find(function(c){
+ return c.$id === columnId;
+ })
+ };
}
- }
+ };
}
class HeaderCellController{
@@ -1756,1315 +1578,1973 @@ function HeaderCellDirective($compile){
if(ctrl.column.headerTemplate || ctrl.column.headerRenderer){
cellScope = ctrl.options.$outer.$new(false);
- // copy some props
- cellScope.$header = ctrl.column.name;
- cellScope.$index = $scope.$index;
- }
+ // copy some props
+ cellScope.$header = ctrl.column.name;
+ cellScope.$index = $scope.$index;
+ }
+
+ if(ctrl.column.headerTemplate){
+ let elm = angular$1.element(`${ctrl.column.headerTemplate.trim()} `);
+ angular$1.element(label).append($compile(elm)(cellScope));
+ } else if(ctrl.column.headerRenderer){
+ let elm = angular$1.element(ctrl.column.headerRenderer($elm));
+ angular$1.element(label).append($compile(elm)(cellScope)[0]);
+ } else {
+ let val = ctrl.column.name;
+ if(val === undefined || val === null) val = '';
+ label.textContent = val;
+ }
+ }
+ }
+ }
+ };
+}
+
+class BodyController{
+
+ /**
+ * A tale body controller
+ * @param {$scope}
+ * @param {$timeout}
+ * @return {BodyController}
+ */
+ /*@ngInject*/
+ constructor($scope, $timeout){
+ this.$scope = $scope;
+ this.tempRows = [];
+
+ this.treeColumn = this.options.columns.find((c) => {
+ return c.isTreeColumn;
+ });
+
+ this.groupColumn = this.options.columns.find((c) => {
+ return c.group;
+ });
+
+ $scope.$watchCollection('body.rows', this.rowsUpdated.bind(this));
+
+ if(this.options.scrollbarV || (!this.options.scrollbarV && this.options.paging.externalPaging)){
+ var sized = false;
+ $scope.$watch('body.options.paging.size', (newVal, oldVal) => {
+ if(!sized || newVal > oldVal){
+ this.getRows();
+ sized = true;
+ }
+ });
+
+ $scope.$watch('body.options.paging.count', (count) => {
+ this.count = count;
+ this.updatePage();
+ });
+
+ $scope.$watch('body.options.paging.offset', (newVal) => {
+ if(this.options.paging.size){
+ this.onPage({
+ offset: newVal,
+ size: this.options.paging.size
+ });
+ }
+ });
+ }
+ }
+
+ rowsUpdated(newVal, oldVal){
+ if(newVal) {
+ if(!this.options.paging.externalPaging){
+ this.options.paging.count = newVal.length;
+ }
+
+ this.count = this.options.paging.count;
+
+ if(this.treeColumn || this.groupColumn){
+ this.buildRowsByGroup();
+ }
+
+ if(this.options.scrollbarV){
+ let refresh = newVal && oldVal && (newVal.length === oldVal.length
+ || newVal.length < oldVal.length);
+
+ this.getRows(refresh);
+ } else {
+ let rows = this.rows;
+
+ if(this.treeColumn){
+ rows = this.buildTree();
+ } else if(this.groupColumn){
+ rows = this.buildGroups();
+ }
+
+ if(this.options.paging.externalPaging){
+ let idxs = this.getFirstLastIndexes(),
+ idx = idxs.first;
- if(ctrl.column.headerTemplate){
- let elm = angular.element(`${ctrl.column.headerTemplate.trim()} `);
- angular.element(label).append($compile(elm)(cellScope));
- } else if(ctrl.column.headerRenderer){
- let elm = angular.element(ctrl.column.headerRenderer($elm));
- angular.element(label).append($compile(elm)(cellScope)[0]);
- } else {
- let val = ctrl.column.name;
- if(val === undefined || val === null) val = '';
- label.textContent = val;
+ this.tempRows.splice(0, this.tempRows.length);
+ while(idx < idxs.last){
+ this.tempRows.push(rows[idx++]);
}
+ } else {
+ this.tempRows.splice(0, this.tempRows.length);
+ this.tempRows.push(...rows);
}
}
}
- };
-}
-
-class HeaderController {
+ }
/**
- * Returns the styles for the header directive.
- * @param {object} scope
- * @return {object} styles
+ * Gets the first and last indexes based on the offset, row height, page size, and overall count.
*/
- styles() {
- return {
- width: this.options.internal.innerWidth + 'px',
- height: this.options.headerHeight + 'px'
+ getFirstLastIndexes(){
+ var firstRowIndex, endIndex;
+
+ if(this.options.scrollbarV){
+ firstRowIndex = Math.max(Math.floor((
+ this.options.internal.offsetY || 0) / this.options.rowHeight, 0), 0);
+ endIndex = Math.min(firstRowIndex + this.options.paging.size, this.count);
+ } else {
+ if(this.options.paging.externalPaging){
+ firstRowIndex = Math.max(this.options.paging.offset * this.options.paging.size, 0);
+ endIndex = Math.min(firstRowIndex + this.options.paging.size, this.count);
+ } else {
+ endIndex = this.count;
+ }
}
- }
- /**
- * Returns the inner styles for the header directive
- * @param {object} scope
- * @return {object} styles
- */
- innerStyles(){
return {
- width: this.columnWidths.total + 'px'
+ first: firstRowIndex,
+ last: endIndex
};
}
/**
- * Invoked when a column sort direction has changed
- * @param {object} scope
- * @param {object} column
+ * Updates the page's offset given the scroll position.
*/
- onSorted(sortedColumn){
- if (this.options.sortType === 'single') {
- // if sort type is single, then only one column can be sorted at once,
- // so we set the sort to undefined for the other columns
- function unsortColumn(column) {
- if (column !== sortedColumn) {
- column.sort = undefined;
- }
- }
+ updatePage(){
+ let curPage = this.options.paging.offset,
+ idxs = this.getFirstLastIndexes();
- this.columns.left.forEach(unsortColumn);
- this.columns.center.forEach(unsortColumn);
- this.columns.right.forEach(unsortColumn);
+ if (this.options.internal.oldScrollPosition === undefined){
+ this.options.internal.oldScrollPosition = 0;
}
- this.onSort({
- column: sortedColumn
- });
- }
+ let oldScrollPosition = this.options.internal.oldScrollPosition,
+ newPage = idxs.first / this.options.paging.size;
- /**
- * Returns the styles by group for the headers.
- * @param {scope}
- * @param {group}
- * @return {styles object}
- */
- stylesByGroup(group){
- var styles = {
- width: this.columnWidths[group] + 'px'
- };
+ this.options.internal.oldScrollPosition = newPage;
- if(group === 'center'){
- TranslateXY(styles, this.options.internal.offsetX * -1, 0);
- } else if(group === 'right'){
- var offset = (this.columnWidths.total - this.options.internal.innerWidth) *-1;
- TranslateXY(styles, offset, 0);
+ if (newPage < oldScrollPosition) {
+ // scrolling up
+ newPage = Math.floor(newPage);
+ } else if (newPage > oldScrollPosition){
+ // scrolling down
+ newPage = Math.ceil(newPage);
+ } else {
+ // equal, just stay on the current page
+ newPage = curPage;
}
- return styles;
+ if(!isNaN(newPage)){
+ this.options.paging.offset = newPage;
+ }
}
/**
- * Invoked when the header cell directive's checkbox has changed.
- * @param {scope}
- */
- onCheckboxChanged(){
- this.onCheckboxChange();
+ * Recursively calculate row depth for unsorted backend data
+ * @param row
+ * @param depth
+ * @return {Integer}
+ */
+ calculateDepth(row, depth=0){
+ var parentProp = this.treeColumn ? this.treeColumn.relationProp : this.groupColumn.prop;
+ var prop = this.treeColumn.prop;
+ if (!row[parentProp]){
+ return depth;
+ }
+ if (row.$$depth) {
+ return row.$$depth + depth;
+ }
+ /* Get data from cache, if exists*/
+ var cachedParent = this.index[row[parentProp]];
+ if (cachedParent) {
+ depth += 1;
+ return this.calculateDepth(cachedParent, depth);
+ }
+ for (var i=0, len = this.rows.length; i < len; i++){
+ var parent = this.rows[i];
+ if (parent[prop] == row[parentProp]){
+ depth+=1;
+ return this.calculateDepth(parent, depth);
+ }
+ }
+ return depth;
}
/**
- * Occurs when a header cell directive triggered a resize
- * @param {object} scope
- * @param {object} column
- * @param {int} width
+ * Matches groups to their respective parents by index.
+ *
+ * Example:
+ *
+ * {
+ * "Acme" : [
+ * { name: "Acme Holdings", parent: "Acme" }
+ * ],
+ * "Acme Holdings": [
+ * { name: "Acme Ltd", parent: "Acme Holdings" }
+ * ]
+ * }
+ *
*/
- onResized(column, width){
- this.onResize({
- column: column,
- width: width
- });
- }
-
-}
+ buildRowsByGroup(){
+ this.index = {};
+ this.rowsByGroup = {};
-function HeaderDirective($timeout){
- return {
- restrict: 'E',
- controller: HeaderController,
- controllerAs: 'header',
- scope: true,
- bindToController: {
- options: '=',
- columns: '=',
- columnWidths: '=',
- onSort: '&',
- onResize: '&',
- onCheckboxChange: '&'
- },
- template: `
- `,
- replace:true,
- link: function($scope, $elm, $attrs, ctrl){
+ for(var i = 0, len = this.rows.length; i < len; i++) {
+ var row = this.rows[i];
+ // build groups
+ var relVal = row[parentProp];
+ if(relVal){
+ if(this.rowsByGroup[relVal]){
+ this.rowsByGroup[relVal].push(row);
+ } else {
+ this.rowsByGroup[relVal] = [ row ];
+ }
+ }
- $scope.columnsResorted = function(event, columnId){
- var col = findColumnById(columnId),
- parent = angular.element(event.currentTarget),
- newIdx = -1;
+ // build indexes
+ if(this.treeColumn){
+ var prop = this.treeColumn.prop;
+ this.index[row[prop]] = row;
- angular.forEach(parent.children(), (c, i) => {
- if (columnId === angular.element(c).attr('data-id')) {
- newIdx = i;
+ if (row[parentProp] === undefined){
+ row.$$depth = 0;
+ } else {
+ var parent = this.index[row[parentProp]];
+ if (parent === undefined){
+ for (var j=0; j < len; j++){
+ if (this.rows[j][prop] == relVal){
+ parent = this.rows[j];
+ break;
+ }
+ }
}
- });
+ if (parent.$$depth === undefined) {
+ parent.$$depth = this.calculateDepth(parent);
+ }
+ row.$$depth = parent.$$depth + 1;
+ if (parent.$$children){
+ parent.$$children.push(row[prop]);
+ } else {
+ parent.$$children = [row[prop]];
+ }
+ }
+ }
+ }
+ }
- $timeout(() => {
- angular.forEach(ctrl.columns, (group) => {
- var idx = group.indexOf(col);
- if(idx > -1){
+ /**
+ * Rebuilds the groups based on what is expanded.
+ * This function needs some optimization, todo for future release.
+ * @return {Array} the temp array containing expanded rows
+ */
+ buildGroups(){
+ var temp = [];
- // this is tricky because we want to update the index
- // in the orig columns array instead of the grouped one
- var curColAtIdx = group[newIdx],
- siblingIdx = ctrl.options.columns.indexOf(curColAtIdx),
- curIdx = ctrl.options.columns.indexOf(col);
+ angular$1.forEach(this.rowsByGroup, (v, k) => {
+ temp.push({
+ name: k,
+ group: true
+ });
- ctrl.options.columns.splice(curIdx, 1);
- ctrl.options.columns.splice(siblingIdx, 0, col);
+ if(this.expanded[k]){
+ temp.push(...v);
+ }
+ });
- return false;
- }
- });
+ return temp;
+ }
- });
- }
+ /**
+ * Returns if the row is selected
+ * @param {row}
+ * @return {Boolean}
+ */
+ isSelected(row){
+ var selected = false;
- var findColumnById = function(columnId){
- var columns = ctrl.columns.left.concat(ctrl.columns.center).concat(ctrl.columns.right)
- return columns.find(function(c){
- return c.$id === columnId;
- })
+ if(this.options.selectable){
+ if(this.options.multiSelect){
+ selected = this.selected.indexOf(row) > -1;
+ } else {
+ selected = this.selected === row;
}
}
- };
-}
+ return selected;
+ }
-/**
- * Sortable Directive
- * http://jsfiddle.net/RubaXa/zLq5J/3/
- * https://jsfiddle.net/hrohxze0/6/
- * @param {function}
- */
-function SortableDirective($timeout) {
- return {
- restrict: 'A',
- scope: {
- isSortable: '=sortable',
- onSortableSort: '&'
- },
- link: function($scope, $element, $attrs){
- var rootEl = $element[0], dragEl, nextEl, dropEl;
+ /**
+ * Creates a tree of the existing expanded values
+ * @return {array} the built tree
+ */
+ buildTree(){
+ var temp = [],
+ self = this;
- function isbefore(a, b) {
- if (a.parentNode == b.parentNode) {
- for (var cur = a; cur; cur = cur.previousSibling) {
- if (cur === b) {
- return true;
- }
- }
- }
- return false;
- };
+ function addChildren(fromArray, toArray, level) {
+ fromArray.forEach(function (row) {
+ var relVal = row[self.treeColumn.relationProp],
+ key = row[self.treeColumn.prop],
+ groupRows = self.rowsByGroup[key],
+ expanded = self.expanded[key];
- function onDragEnter(e) {
- var target = e.target;
- if (isbefore(dragEl, target)) {
- target.parentNode.insertBefore(dragEl, target);
- } else if(target.nextSibling && target.hasAttribute('draggable')) {
- target.parentNode.insertBefore(dragEl, target.nextSibling.nextSibling);
+ if (level > 0 || !relVal) {
+ toArray.push(row);
+ if (groupRows && groupRows.length > 0 && expanded) {
+ addChildren(groupRows, toArray, level + 1);
+ }
}
- };
-
- function onDragEnd(evt) {
- evt.preventDefault();
-
- dragEl.classList.remove('dt-clone');
-
- $element.off('dragend', onDragEnd);
- $element.off('dragenter', onDragEnter);
- if (nextEl !== dragEl.nextSibling) {
- $scope.onSortableSort({
- event: evt,
- columnId: angular.element(dragEl).attr('data-id')
- });
- }
- };
+ });
+ }
- function onDragStart(evt){
- if(!$scope.isSortable) return false;
- evt = evt.originalEvent || evt;
+ addChildren(this.rows, temp, 0);
- dragEl = evt.target;
- nextEl = dragEl.nextSibling;
- dragEl.classList.add('dt-clone');
+ return temp;
+ }
- evt.dataTransfer.effectAllowed = 'move';
- evt.dataTransfer.setData('Text', dragEl.textContent);
+ /**
+ * Creates the intermediate collection that is shown in the view.
+ * @param {boolean} refresh - bust the tree/group cache
+ */
+ getRows(refresh){
+ // only proceed when we have pre-aggregated the values
+ if((this.treeColumn || this.groupColumn) && !this.rowsByGroup){
+ return false;
+ }
- $element.on('dragenter', onDragEnter);
- $element.on('dragend', onDragEnd);
- };
+ var temp;
- $element.on('dragstart', onDragStart);
+ if(this.treeColumn) {
+ temp = this.treeTemp || [];
+ // cache the tree build
+ if((refresh || !this.treeTemp)){
+ this.treeTemp = temp = this.buildTree();
+ this.count = temp.length;
- $scope.$on('$destroy', () => {
- $element.off('dragstart', onDragStart);
- });
+ // have to force reset, optimize this later
+ this.tempRows.splice(0, this.tempRows.length);
+ }
+ } else if(this.groupColumn) {
+ temp = this.groupsTemp || [];
+ // cache the group build
+ if((refresh || !this.groupsTemp)){
+ this.groupsTemp = temp = this.buildGroups();
+ this.count = temp.length;
+ }
+ } else {
+ temp = this.rows;
+ if(refresh === true){
+ this.tempRows.splice(0, this.tempRows.length);
+ }
}
- }
-}
+ var idx = 0,
+ indexes = this.getFirstLastIndexes(),
+ rowIndex = indexes.first;
-/**
- * Resizable directive
- * http://stackoverflow.com/questions/18368485/angular-js-resizable-div-directive
- * @param {object}
- * @param {function}
- * @param {function}
- */
-function ResizableDirective($document, $timeout){
- return {
- restrict: 'A',
- scope:{
- isResizable: '=resizable',
- minWidth: '=',
- maxWidth: '=',
- onResize: '&'
- },
- link: function($scope, $element, $attrs){
- if($scope.isResizable){
- $element.addClass('resizable');
+ // slice out the old rows so we don't have duplicates
+ this.tempRows.splice(0, indexes.last - indexes.first);
+
+ while (rowIndex < indexes.last && rowIndex < this.count) {
+ var row = temp[rowIndex];
+ if(row){
+ row.$$index = rowIndex;
+ this.tempRows[idx] = row;
}
+ idx++;
+ rowIndex++;
+ }
- var handle = angular.element(` `),
- parent = $element.parent(),
- prevScreenX;
+ this.options.internal.styleTranslator.update(this.tempRows);
- handle.on('mousedown', function(event) {
- if(!$element[0].classList.contains('resizable')) {
- return false;
- }
+ return this.tempRows;
+ }
- event.stopPropagation();
- event.preventDefault();
+ /**
+ * Returns the styles for the table body directive.
+ * @return {object}
+ */
+ styles(){
+ var styles = {
+ width: this.options.internal.innerWidth + 'px'
+ };
- $document.on('mousemove', mousemove);
- $document.on('mouseup', mouseup);
- });
+ if(!this.options.scrollbarV){
+ styles.overflowY = 'hidden';
+ } else if(this.options.scrollbarH === false){
+ styles.overflowX = 'hidden';
+ }
- function mousemove(event) {
- event = event.originalEvent || event;
+ if(this.options.scrollbarV){
+ styles.height = this.options.internal.bodyHeight + 'px';
+ }
- var width = parent[0].clientWidth,
- movementX = event.movementX || event.mozMovementX || (event.screenX - prevScreenX),
- newWidth = width + (movementX || 0);
+ return styles;
+ }
- prevScreenX = event.screenX;
+ /**
+ * Returns the styles for the row diretive.
+ * @param {row}
+ * @return {styles object}
+ */
+ rowStyles(row){
+ let styles = {};
- if((!$scope.minWidth || newWidth >= $scope.minWidth) && (!$scope.maxWidth || newWidth <= $scope.maxWidth)){
- parent.css({
- width: newWidth + 'px'
- });
- }
- }
+ if(this.options.rowHeight === 'auto'){
+ styles.height = this.options.rowHeight + 'px';
+ }
- function mouseup() {
- if ($scope.onResize) {
- $timeout(function () {
- let width = parent[0].clientWidth;
- if (width < $scope.minWidth){
- width = $scope.minWidth;
- }
- $scope.onResize({ width: width });
- });
- }
+ return styles;
+ }
- $document.unbind('mousemove', mousemove);
- $document.unbind('mouseup', mouseup);
- }
+ /**
+ * Builds the styles for the row group directive
+ * @param {object} row
+ * @return {object} styles
+ */
+ groupRowStyles(row){
+ var styles = this.rowStyles(row);
+ styles.width = this.columnWidths.total + 'px';
+ return styles;
+ }
- $element.append(handle);
+ /**
+ * Returns the css classes for the row directive.
+ * @param {row}
+ * @return {css class object}
+ */
+ rowClasses(row){
+ var styles = {
+ 'selected': this.isSelected(row),
+ 'dt-row-even': row && row.$$index%2 === 0,
+ 'dt-row-odd': row && row.$$index%2 !== 0
+ };
+
+ if(this.treeColumn){
+ // if i am a child
+ styles['dt-leaf'] = this.rowsByGroup[row[this.treeColumn.relationProp]];
+ // if i have children
+ styles['dt-has-leafs'] = this.rowsByGroup[row[this.treeColumn.prop]];
+ // the depth
+ styles['dt-depth-' + row.$$depth] = true;
}
- };
-}
+ return styles;
+ }
-/**
- * Throttle helper
- * @param {function}
- * @param {boolean}
- * @param {object}
- */
-function throttle(func, wait, options) {
- var context, args, result;
- var timeout = null;
- var previous = 0;
- options || (options = {});
- var later = function() {
- previous = options.leading === false ? 0 : new Date();
- timeout = null;
- result = func.apply(context, args);
- };
- return function() {
- var now = new Date();
- if (!previous && options.leading === false)
- previous = now;
- var remaining = wait - (now - previous);
- context = this;
- args = arguments;
- if (remaining <= 0) {
- clearTimeout(timeout);
- timeout = null;
- previous = now;
- result = func.apply(context, args);
- } else if (!timeout && options.trailing !== false) {
- timeout = setTimeout(later, remaining);
+ /**
+ * Returns the row model for the index in the view.
+ * @param {index}
+ * @return {row model}
+ */
+ getRowValue(idx){
+ return this.tempRows[idx];
+ }
+
+ /**
+ * Calculates if a row is expanded or collasped for tree grids.
+ * @param {row}
+ * @return {boolean}
+ */
+ getRowExpanded(row){
+ if(this.treeColumn) {
+ return this.expanded[row[this.treeColumn.prop]];
+ } else if(this.groupColumn){
+ return this.expanded[row.name];
}
- return result;
- };
-}
+ }
+ /**
+ * Calculates if the row has children
+ * @param {row}
+ * @return {boolean}
+ */
+ getRowHasChildren(row){
+ if(!this.treeColumn) return;
+ var children = this.rowsByGroup[row[this.treeColumn.prop]];
+ return children !== undefined || (children && !children.length);
+ }
-/**
- * Gets the width of the scrollbar. Nesc for windows
- * http://stackoverflow.com/a/13382873/888165
- * @return {int} width
- */
-function ScrollbarWidth() {
- var outer = document.createElement("div");
- outer.style.visibility = "hidden";
- outer.style.width = "100px";
- outer.style.msOverflowStyle = "scrollbar";
- document.body.appendChild(outer);
+ /**
+ * Tree toggle event from a cell
+ * @param {row model}
+ * @param {cell model}
+ */
+ onTreeToggled(row, cell){
+ var val = row[this.treeColumn.prop];
+ this.expanded[val] = !this.expanded[val];
- var widthNoScroll = outer.offsetWidth;
- outer.style.overflow = "scroll";
+ if(this.options.scrollbarV){
+ this.getRows(true);
+ } else {
+ var values = this.buildTree();
+ this.tempRows.splice(0, this.tempRows.length);
+ this.tempRows.push(...values);
+ }
- var inner = document.createElement("div");
- inner.style.width = "100%";
- outer.appendChild(inner);
+ this.onTreeToggle({
+ row: row,
+ cell: cell
+ });
+ }
- var widthWithScroll = inner.offsetWidth;
- outer.parentNode.removeChild(outer);
+ /**
+ * Invoked when the row group directive was expanded
+ * @param {object} row
+ */
+ onGroupToggle(row){
+ this.expanded[row.name] = !this.expanded[row.name];
- return widthNoScroll - widthWithScroll;
+ if(this.options.scrollbarV){
+ this.getRows(true);
+ } else {
+ var values = this.buildGroups();
+ this.tempRows.splice(0, this.tempRows.length);
+ this.tempRows.push(...values);
+ }
+ }
+}
+
+function BodyDirective($timeout){
+ return {
+ restrict: 'E',
+ controller: BodyController,
+ controllerAs: 'body',
+ bindToController: {
+ columns: '=',
+ columnWidths: '=',
+ rows: '=',
+ options: '=',
+ selected: '=?',
+ expanded: '=?',
+ onPage: '&',
+ onTreeToggle: '&',
+ onSelect: '&',
+ onRowClick: '&',
+ onRowDblClick: '&'
+ },
+ scope: true,
+ template: `
+
+ `
+ };
}
-let DataTableService = {
+/**
+ * This translates the dom position based on the model row index.
+ * This only exists because Angular's binding process is too slow.
+ */
+class StyleTranslator{
- // id: [ column defs ]
- columns: {},
- dTables: {},
+ constructor(height){
+ this.height = height;
+ this.map = new Map();
+ }
- saveColumns(id, columnElms) {
- if (columnElms && columnElms.length) {
- let columnsArray = [].slice.call(columnElms);
- this.dTables[id] = columnsArray;
+ /**
+ * Update the rows
+ * @param {Array} rows
+ */
+ update(rows){
+ let n = 0;
+ while (n <= this.map.size) {
+ let dom = this.map.get(n);
+ let model = rows[n];
+ if(dom && model){
+ TranslateXY(dom[0].style, 0, model.$$index * this.height);
+ }
+ n++;
}
- },
+ }
/**
- * Create columns from elements
- * @param {array} columnElms
+ * Register the row
+ * @param {int} idx
+ * @param {dom} dom
*/
- buildColumns(scope, parse) {
- //FIXME: Too many nested for loops. O(n3)
+ register(idx, dom){
+ this.map.set(idx, dom);
+ }
- // Iterate through each dTable
- angular.forEach(this.dTables, (columnElms, id) => {
- this.columns[id] = [];
+}
- // Iterate through each column
- angular.forEach(columnElms, (c) => {
- let column = {};
+function ScrollerDirective($timeout, $rootScope){
+ return {
+ restrict: 'E',
+ require:'^dtBody',
+ transclude: true,
+ replace: true,
+ template: `
`,
+ link: function($scope, $elm, $attrs, ctrl){
+ var ticking = false,
+ lastScrollY = 0,
+ lastScrollX = 0,
+ parent = $elm.parent();
- var visible = true;
- // Iterate through each attribute
- angular.forEach(c.attributes, (attr) => {
- let attrName = CamelCase(attr.name);
+ ctrl.options.internal.styleTranslator =
+ new StyleTranslator(ctrl.options.rowHeight);
- // cuz putting className vs class on
- // a element feels weird
- switch (attrName) {
- case 'class':
- column.className = attr.value;
- break;
- case 'name':
- case 'prop':
- column[attrName] = attr.value;
- break;
- case 'headerRenderer':
- case 'cellRenderer':
- case 'cellDataGetter':
- column[attrName] = parse(attr.value);
- break;
- case 'visible':
- visible = parse(attr.value)(scope);
- break;
- default:
- column[attrName] = parse(attr.value)(scope);
- break;
- }
- });
+ ctrl.options.internal.setYOffset = function(offsetY){
+ parent[0].scrollTop = offsetY;
+ };
- let header = c.getElementsByTagName('column-header');
- if(header.length){
- column.headerTemplate = header[0].innerHTML;
- c.removeChild(header[0])
- }
+ function update(){
+ ctrl.options.internal.offsetY = lastScrollY;
+ ctrl.options.internal.offsetX = lastScrollX;
+ ctrl.updatePage();
- if (c.innerHTML !== '') {
- column.template = c.innerHTML;
+ if(ctrl.options.scrollbarV){
+ ctrl.getRows();
}
- if (visible)
- this.columns[id].push(column);
- });
- });
-
- this.dTables = {};
- }
-};
-
-
-/**
- * Creates a unique object id.
- */
-function ObjectId() {
- var timestamp = (new Date().getTime() / 1000 | 0).toString(16);
- return timestamp + 'xxxxxxxxxxxxxxxx'.replace(/[x]/g, function () {
- return (Math.random() * 16 | 0).toString(16);
- }).toLowerCase();
-}
-
+ // https://github.com/Swimlane/angular-data-table/pull/74
+ ctrl.options.$outer.$digest();
-/**
- * Resizes columns based on the flexGrow property, while respecting manually set widths
- * @param {array} colsByGroup
- * @param {int} maxWidth
- * @param {int} totalFlexGrow
- */
-function ScaleColumns(colsByGroup, maxWidth, totalFlexGrow) {
- // calculate total width and flexgrow points for coulumns that can be resized
- angular.forEach(colsByGroup, (cols) => {
- cols.forEach((column) => {
- if (!column.canAutoResize){
- maxWidth -= column.width;
- totalFlexGrow -= column.flexGrow;
- } else {
- column.width = 0;
+ ticking = false;
}
- });
- });
- var hasMinWidth = {}
- var remainingWidth = maxWidth;
-
- // resize columns until no width is left to be distributed
- do {
- let widthPerFlexPoint = remainingWidth / totalFlexGrow;
- remainingWidth = 0;
- angular.forEach(colsByGroup, (cols) => {
- cols.forEach((column, i) => {
- // if the column can be resize and it hasn't reached its minimum width yet
- if (column.canAutoResize && !hasMinWidth[i]){
- let newWidth = column.width + column.flexGrow * widthPerFlexPoint;
- if (column.minWidth !== undefined && newWidth < column.minWidth){
- remainingWidth += newWidth - column.minWidth;
- column.width = column.minWidth;
- hasMinWidth[i] = true;
- } else {
- column.width = newWidth;
- }
+ function requestTick() {
+ if(!ticking) {
+ requestAnimFrame(update);
+ ticking = true;
}
- });
- });
- } while (remainingWidth !== 0);
+ }
-}
+ parent.on('scroll', function(ev) {
+ lastScrollY = this.scrollTop;
+ lastScrollX = this.scrollLeft;
+ requestTick();
+ });
+ $scope.$on('$destroy', () => {
+ parent.off('scroll');
+ });
-/**
- * Returns the columns by pin.
- * @param {array} colsumns
- */
-function ColumnsByPin(cols){
- var ret = {
- left: [],
- center: [],
- right: []
- };
+ $scope.scrollerStyles = function(){
+ if(ctrl.options.scrollbarV){
+ return {
+ height: ctrl.count * ctrl.options.rowHeight + 'px'
+ }
+ }
+ };
- for(var i=0, len=cols.length; i < len; i++) {
- var c = cols[i];
- if(c.frozenLeft){
- ret.left.push(c)
- } else if(c.frozenRight){
- ret.right.push(c);
- } else {
- ret.center.push(c);
}
- }
-
- return ret;
+ };
}
-
/**
- * Calculates the Total Flex Grow
- * @param {array}
+ * Shortcut for key handlers
+ * @type {Object}
*/
-function GetTotalFlexGrow(columns){
- var totalFlexGrow = 0;
-
- for (let c of columns) {
- totalFlexGrow += c.flexGrow || 0;
- }
-
- return totalFlexGrow;
-}
+var KEYS = {
+ BACKSPACE: 8,
+ TAB: 9,
+ RETURN: 13,
+ ALT: 18,
+ ESC: 27,
+ SPACE: 32,
+ PAGE_UP: 33,
+ PAGE_DOWN: 34,
+ END: 35,
+ HOME: 36,
+ LEFT: 37,
+ UP: 38,
+ RIGHT: 39,
+ DOWN: 40,
+ DELETE: 46,
+ COMMA: 188,
+ PERIOD: 190,
+ A: 65,
+ Z: 90,
+ ZERO: 48,
+ NUMPAD_0: 96,
+ NUMPAD_9: 105
+};
+class SelectionController {
-/**
- * Calculates the total width of all columns and their groups
- * @param {array} columns
- * @param {string} property width to get
- */
-function ColumnTotalWidth(columns, prop) {
- var totalWidth = 0;
+ /*@ngInject*/
+ constructor($scope){
+ this.body = $scope.body;
+ this.options = $scope.body.options;
+ this.selected = $scope.body.selected;
+ }
- columns.forEach((c) => {
- var has = prop && c[prop];
- totalWidth = totalWidth + (has ? c[prop] : c.width);
- });
+ /**
+ * Handler for the keydown on a row
+ * @param {event}
+ * @param {index}
+ * @param {row}
+ */
+ keyDown(ev, index, row){
+ if(KEYS[ev.keyCode]){
+ ev.preventDefault();
+ }
- return totalWidth;
-}
+ if (ev.keyCode === KEYS.DOWN) {
+ var next = ev.target.nextElementSibling;
+ if(next){
+ next.focus();
+ }
+ } else if (ev.keyCode === KEYS.UP) {
+ var prev = ev.target.previousElementSibling;
+ if(prev){
+ prev.focus();
+ }
+ } else if(ev.keyCode === KEYS.RETURN){
+ this.selectRow(index, row);
+ }
+ }
+ /**
+ * Handler for the row click event
+ * @param {object} event
+ * @param {int} index
+ * @param {object} row
+ */
+ rowClicked(event, index, row){
+ if(!this.options.checkboxSelection){
+ // event.preventDefault();
+ this.selectRow(event, index, row);
+ }
-/**
- * Adjusts the column widths.
- * Inspired by: https://github.com/facebook/fixed-data-table/blob/master/src/FixedDataTableWidthHelper.js
- * @param {array} all columns
- * @param {int} width
- */
-function AdjustColumnWidths(allColumns, expectedWidth){
- var columnsWidth = ColumnTotalWidth(allColumns),
- totalFlexGrow = GetTotalFlexGrow(allColumns),
- colsByGroup = ColumnsByPin(allColumns);
+ this.body.onRowClick({ row: row });
+ }
+
+ /**
+ * Handler for the row double click event
+ * @param {object} event
+ * @param {int} index
+ * @param {object} row
+ */
+ rowDblClicked(event, index, row){
+ if(!this.options.checkboxSelection){
+ event.preventDefault();
+ this.selectRow(event, index, row);
+ }
- if (columnsWidth !== expectedWidth){
- ScaleColumns(colsByGroup, expectedWidth, totalFlexGrow);
+ this.body.onRowDblClick({ row: row });
}
-}
+ /**
+ * Invoked when a row directive's checkbox was changed.
+ * @param {index}
+ * @param {row}
+ */
+ onCheckboxChange(event, index, row){
+ this.selectRow(event, index, row);
+ }
-/**
- * Forces the width of the columns to
- * distribute equally but overflowing when nesc.
- *
- * Rules:
- *
- * - If combined withs are less than the total width of the grid,
- * proporation the widths given the min / max / noraml widths to fill the width.
- *
- * - If the combined widths, exceed the total width of the grid,
- * use the standard widths.
- *
- * - If a column is resized, it should always use that width
- *
- * - The proporational widths should never fall below min size if specified.
- *
- * - If the grid starts off small but then becomes greater than the size ( + / - )
- * the width should use the orginial width; not the newly proporatied widths.
- *
- * @param {array} allColumns
- * @param {int} expectedWidth
- */
-function ForceFillColumnWidths(allColumns, expectedWidth, startIdx){
- var contentWidth = 0,
- columnsToResize = startIdx > -1 ?
- allColumns.slice(startIdx, allColumns.length).filter((c) => { return c.canAutoResize }) :
- allColumns.filter((c) => { return c.canAutoResize });
+ /**
+ * Selects a row and places in the selection collection
+ * @param {index}
+ * @param {row}
+ */
+ selectRow(event, index, row){
+ if(this.options.selectable){
+ if(this.options.multiSelect){
+ var isCtrlKeyDown = event.ctrlKey || event.metaKey,
+ isShiftKeyDown = event.shiftKey;
- allColumns.forEach((c) => {
- if(!c.canAutoResize){
- contentWidth += c.width;
- } else {
- contentWidth += (c.$$oldWidth || c.width);
+ if(isShiftKeyDown){
+ this.selectRowsBetween(index, row);
+ } else {
+ var idx = this.selected.indexOf(row);
+ if(idx > -1){
+ this.selected.splice(idx, 1);
+ } else {
+ if(this.options.multiSelectOnShift && this.selected.length === 1) {
+ this.selected.splice(0, 1);
+ }
+ this.selected.push(row);
+ this.body.onSelect({ rows: [ row ] });
+ }
+ }
+ this.prevIndex = index;
+ } else {
+ this.selected = row;
+ this.body.onSelect({ rows: [ row ] });
+ }
}
- });
+ }
- var remainingWidth = expectedWidth - contentWidth,
- additionWidthPerColumn = remainingWidth / columnsToResize.length,
- exceedsWindow = contentWidth > expectedWidth;
+ /**
+ * Selects the rows between a index. Used for shift click selection.
+ * @param {index}
+ */
+ selectRowsBetween(index){
+ var reverse = index < this.prevIndex,
+ selecteds = [];
- columnsToResize.forEach((column) => {
- if(exceedsWindow){
- column.width = column.$$oldWidth || column.width;
- } else {
- if(!column.$$oldWidth){
- column.$$oldWidth = column.width;
- }
+ for(var i=0, len=this.body.rows.length; i < len; i++) {
+ var row = this.body.rows[i],
+ greater = i >= this.prevIndex && i <= index,
+ lesser = i <= this.prevIndex && i >= index;
- var newSize = column.$$oldWidth + additionWidthPerColumn;
- if(column.minWith && newSize < column.minWidth){
- column.width = column.minWidth;
- } else if(column.maxWidth && newSize > column.maxWidth){
- column.width = column.maxWidth;
+ var range = {};
+ if ( reverse ) {
+ range = {
+ start: index,
+ end: ( this.prevIndex - index )
+ };
} else {
- column.width = newSize;
+ range = {
+ start: this.prevIndex,
+ end: index + 1
+ };
+ }
+
+ if((reverse && lesser) || (!reverse && greater)){
+ var idx = this.selected.indexOf(row);
+ // if reverse shift selection (unselect) and the
+ // row is already selected, remove it from selected
+ if ( reverse && idx > -1 ) {
+ this.selected.splice(idx, 1);
+ continue;
+ }
+ // if in the positive range to be added to `selected`, and
+ // not already in the selected array, add it
+ if( i >= range.start && i < range.end ){
+ if ( idx === -1 ) {
+ this.selected.push(row);
+ selecteds.push(row);
+ }
+ }
}
}
- });
-}
+ this.body.onSelect({ rows: selecteds });
+ }
+}
-/**
- * Returns the widths of all group sets of a column
- * @param {object} groups
- * @param {array} all
- */
-function ColumnGroupWidths(groups, all){
+function SelectionDirective(){
return {
- left: ColumnTotalWidth(groups.left),
- center: ColumnTotalWidth(groups.center),
- right: ColumnTotalWidth(groups.right),
- total: ColumnTotalWidth(all)
+ controller: SelectionController,
+ restrict: 'A',
+ require:'^dtBody',
+ controllerAs: 'selCtrl'
};
}
+class RowController {
-/**
- * Default Column Options
- * @type {object}
- */
-const ColumnDefaults = {
-
- // pinned to the left
- frozenLeft: false,
-
- // pinned to the right
- frozenRight: false,
-
- // body cell css class name
- className: undefined,
-
- // header cell css class name
- headerClassName: undefined,
-
- // The grow factor relative to other columns. Same as the flex-grow
- // API from http://www.w3.org/TR/css3-flexbox/. Basically,
- // take any available extra width and distribute it proportionally
- // according to all columns' flexGrow values.
- flexGrow: 0,
-
- // Minimum width of the column.
- minWidth: 100,
-
- //Maximum width of the column.
- maxWidth: undefined,
+ /**
+ * Returns the value for a given column
+ * @param {col}
+ * @return {value}
+ */
+ getValue(col){
+ if(!col.prop) return '';
+ return DeepValueGetter(this.row, col.prop);
+ }
- // The width of the column, by default (in pixels).
- width: 150,
+ /**
+ * Invoked when a cell triggers the tree toggle
+ * @param {cell}
+ */
+ onTreeToggled(cell){
+ this.onTreeToggle({
+ cell: cell,
+ row: this.row
+ });
+ }
- // If yes then the column can be resized, otherwise it cannot.
- resizable: true,
+ /**
+ * Calculates the styles for a pin group
+ * @param {group}
+ * @return {styles object}
+ */
+ stylesByGroup( group){
+ var styles = {
+ width: this.columnWidths[group] + 'px'
+ };
- // Custom sort comparator
- // pass false if you want to server sort
- comparator: undefined,
+ if(group === 'left'){
+ TranslateXY(styles, this.options.internal.offsetX, 0);
+ } else if(group === 'right'){
+ var offset = (((this.columnWidths.total - this.options.internal.innerWidth) -
+ this.options.internal.offsetX) + this.options.internal.scrollBarWidth) * -1;
+ TranslateXY(styles, offset, 0);
+ }
- // If yes then the column can be sorted.
- sortable: true,
+ return styles;
+ }
- // Default sort asecending/descending for the column
- sort: undefined,
+ /**
+ * Invoked when the cell directive's checkbox changed state
+ */
+ onCheckboxChanged(ev){
+ this.onCheckboxChange({
+ $event: ev,
+ row: this.row
+ });
+ }
- // If you want to sort a column by a special property
- // See an example in demos/sort.html
- sortBy: undefined,
+}
- // The cell renderer that returns content for table column header
- headerRenderer: undefined,
+function RowDirective(){
+ return {
+ restrict: 'E',
+ controller: RowController,
+ controllerAs: 'rowCtrl',
+ scope: true,
+ bindToController: {
+ row: '=',
+ columns: '=',
+ columnWidths: '=',
+ expanded: '=',
+ selected: '=',
+ hasChildren: '=',
+ options: '=',
+ onCheckboxChange: '&',
+ onTreeToggle: '&'
+ },
+ link: function($scope, $elm, $attrs, ctrl){
+ if(ctrl.row){
+ // inital render position
+ TranslateXY($elm[0].style, 0, ctrl.row.$$index * ctrl.options.rowHeight);
+ }
- // The cell renderer function(scope, elm) that returns React-renderable content for table cell.
- cellRenderer: undefined,
+ // register w/ the style translator
+ ctrl.options.internal.styleTranslator.register($scope.$index, $elm);
+ },
+ template: `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
`,
+ replace:true
+ };
+}
- // The getter function(value) that returns the cell data for the cellRenderer.
- // If not provided, the cell data will be collected from row data instead.
- cellDataGetter: undefined,
+class GroupRowController {
- // Adds +/- button and makes a secondary call to load nested data
- isTreeColumn: false,
+ onGroupToggled(evt){
+ evt.stopPropagation();
+ this.onGroupToggle({
+ group: this.row
+ });
+ }
- // Adds the checkbox selection to the column
- isCheckboxColumn: false,
+ treeClass(){
+ return {
+ 'dt-tree-toggle': true,
+ 'icon-right': !this.expanded,
+ 'icon-down': this.expanded
+ };
+ }
- // Toggles the checkbox column in the header
- // for selecting all values given to the grid
- headerCheckbox: false,
+}
- // Whether the column can automatically resize to fill space in the table.
- canAutoResize: true
+function GroupRowDirective(){
+ return {
+ restrict: 'E',
+ controller: GroupRowController,
+ controllerAs: 'group',
+ bindToController: {
+ row: '=',
+ onGroupToggle: '&',
+ expanded: '=',
+ options: '='
+ },
+ scope: true,
+ replace:true,
+ template: `
+
+
+
+
+
+
`,
+ link: function($scope, $elm, $attrs, ctrl){
+ // inital render position
+ TranslateXY($elm[0].style, 0, ctrl.row.$$index * ctrl.options.rowHeight);
-};
+ // register w/ the style translator
+ ctrl.options.internal.styleTranslator.register($scope.$index, $elm);
+ }
+ };
+}
+class CellController {
-/**
- * Default Table Options
- * @type {object}
- */
-const TableDefaults = {
+ /**
+ * Calculates the styles for the Cell Directive
+ * @return {styles object}
+ */
+ styles(){
+ return {
+ width: this.column.width + 'px',
+ 'min-width': this.column.width + 'px'
+ };
+ }
- // Enable vertical scrollbars
- scrollbarV: true,
+ /**
+ * Calculates the css classes for the cell directive
+ * @param {column}
+ * @return {class object}
+ */
+ cellClass(){
+ var style = {
+ 'dt-tree-col': this.column.isTreeColumn
+ };
- // Enable horz scrollbars
- // scrollbarH: true,
+ if(this.column.className){
+ style[this.column.className] = true;
+ }
- // The row height, which is necessary
- // to calculate the height for the lazy rendering.
- rowHeight: 30,
+ return style;
+ }
- // flex
- // force
- // standard
- columnMode: 'standard',
+ /**
+ * Calculates the tree class styles.
+ * @return {css classes object}
+ */
+ treeClass(){
+ return {
+ 'dt-tree-toggle': true,
+ 'icon-right': !this.expanded,
+ 'icon-down': this.expanded
+ }
+ }
- // Loading message presented when the array is undefined
- loadingMessage: 'Loading...',
+ /**
+ * Invoked when the tree toggle button was clicked.
+ * @param {event}
+ */
+ onTreeToggled(evt){
+ evt.stopPropagation();
+ this.expanded = !this.expanded;
+ this.onTreeToggle({
+ cell: {
+ value: this.value,
+ column: this.column,
+ expanded: this.expanded
+ }
+ });
+ }
- // Message to show when array is presented
- // but contains no values
- emptyMessage: 'No data to display',
+ /**
+ * Invoked when the checkbox was changed
+ * @param {object} event
+ */
+ onCheckboxChanged(event){
+ event.stopPropagation();
+ this.onCheckboxChange({ $event: event });
+ }
- // The minimum header height in pixels.
- // pass falsey for no header
- headerHeight: 30,
+ /**
+ * Returns the value in its fomatted form
+ * @return {string} value
+ */
+ getValue(){
+ var val = this.column.cellDataGetter ?
+ this.column.cellDataGetter(this.value) : this.value;
- // The minimum footer height in pixels.
- // pass falsey for no footer
- footerHeight: 0,
+ if(val === undefined || val === null) val = '';
+ return val;
+ }
- paging: {
- // if external paging is turned on
- externalPaging: false,
+}
- // Page size
- size: undefined,
+function CellDirective($rootScope, $compile, $log, $timeout){
+ return {
+ restrict: 'E',
+ controller: CellController,
+ scope: true,
+ controllerAs: 'cell',
+ bindToController: {
+ options: '=',
+ value: '=',
+ selected: '=',
+ column: '=',
+ row: '=',
+ expanded: '=',
+ hasChildren: '=',
+ onTreeToggle: '&',
+ onCheckboxChange: '&'
+ },
+ template:
+ `
+
+
+
+
+
+
`,
+ replace: true,
+ compile: function() {
+ return {
+ pre: function($scope, $elm, $attrs, ctrl) {
+ var content = angular$1.element($elm[0].querySelector('.dt-cell-content')), cellScope;
- // Total count
- count: 0,
+ // extend the outer scope onto our new cell scope
+ if(ctrl.column.template || ctrl.column.cellRenderer){
+ createCellScope();
+ }
- // Page offset
- offset: 0,
+ $scope.$watch('cell.row', () => {
+ if(cellScope){
+ cellScope.$destroy();
- // Loading indicator
- loadingIndicator: false
- },
+ createCellScope();
- // if users can select itmes
- selectable: false,
+ cellScope.$cell = ctrl.value;
+ cellScope.$row = ctrl.row;
+ cellScope.$column = ctrl.column;
+ cellScope.$$watchers = null;
+ }
- // if users can select mutliple items
- multiSelect: false,
+ if(ctrl.column.template){
+ content.empty();
+ var elm = angular$1.element(`${ctrl.column.template.trim()} `);
+ content.append($compile(elm)(cellScope));
+ } else if(ctrl.column.cellRenderer){
+ content.empty();
+ var elm = angular$1.element(ctrl.column.cellRenderer(cellScope, content));
+ content.append($compile(elm)(cellScope));
+ } else {
+ content[0].innerHTML = ctrl.getValue();
+ }
+
+ }, true);
- // checkbox selection vs row click
- checkboxSelection: false,
+ function createCellScope(){
+ cellScope = ctrl.options.$outer.$new(false);
+ cellScope.getValue = ctrl.getValue;
+ }
+ }
+ }
+ }
+ };
+}
- // if you can reorder columns
- reorderable: true,
+class FooterController {
- internal: {
- offsetX: 0,
- offsetY: 0,
- innerWidth: 0,
- bodyHeight: 300
+ /**
+ * Creates an instance of the Footer Controller
+ * @param {scope}
+ * @return {[type]}
+ */
+ /*@ngInject*/
+ constructor($scope){
+ this.page = this.paging.offset + 1;
+ $scope.$watch('footer.paging.offset', (newVal) => {
+ this.offsetChanged(newVal);
+ });
}
-};
-
-class DataTableController {
+ /**
+ * The offset ( page ) changed externally, update the page
+ * @param {new offset}
+ */
+ offsetChanged(newVal){
+ this.page = newVal + 1;
+ }
/**
- * Creates an instance of the DataTable Controller
+ * The pager was invoked
* @param {scope}
- * @param {filter}
*/
- /*@ngInject*/
- constructor($scope, $filter, $log, $transclude){
- Object.assign(this, {
- $scope: $scope,
- $filter: $filter,
- $log: $log
+ onPaged(page){
+ this.paging.offset = page - 1;
+ this.onPage({
+ offset: this.paging.offset,
+ size: this.paging.size
});
+ }
- this.defaults();
+}
- // set scope to the parent
- this.options.$outer = $scope.$parent;
+function FooterDirective(){
+ return {
+ restrict: 'E',
+ controller: FooterController,
+ controllerAs: 'footer',
+ scope: true,
+ bindToController: {
+ paging: '=',
+ onPage: '&'
+ },
+ template:
+ ``,
+ replace: true
+ };
+}
- $scope.$watch('dt.options.columns', (newVal, oldVal) => {
- this.transposeColumnDefaults();
+class PagerController {
- if(newVal.length !== oldVal.length){
- this.adjustColumns();
- }
+ /**
+ * Creates an instance of the Pager Controller
+ * @param {object} $scope
+ */
+ /*@ngInject*/
+ constructor($scope){
+ $scope.$watch('pager.count', (newVal) => {
+ this.calcTotalPages(this.size, this.count);
+ this.getPages(this.page || 1);
+ });
- this.calculateColumns();
- }, true);
+ $scope.$watch('pager.size', (newVal) => {
+ this.calcTotalPages(this.size, this.count);
+ this.getPages(this.page || 1);
+ });
- // default sort
- var watch = $scope.$watch('dt.rows', (newVal) => {
- if(newVal){
- watch();
- this.onSorted();
+ $scope.$watch('pager.page', (newVal) => {
+ if (newVal !== 0 && newVal <= this.totalPages) {
+ this.getPages(newVal);
}
});
+
+ this.getPages(this.page || 1);
+ }
+
+ /**
+ * Calculates the total number of pages given the count.
+ * @return {int} page count
+ */
+ calcTotalPages(size, count) {
+ var count = size < 1 ? 1 : Math.ceil(count / size);
+ this.totalPages = Math.max(count || 0, 1);
+ }
+
+ /**
+ * Select a page
+ * @param {int} num
+ */
+ selectPage(num){
+ if (num > 0 && num <= this.totalPages) {
+ this.page = num;
+ this.onPage({
+ page: num
+ });
+ }
+ }
+
+ /**
+ * Selects the previous pager
+ */
+ prevPage(){
+ if (this.page > 1) {
+ this.selectPage(--this.page);
+ }
}
/**
- * Creates and extends default options for the grid control
+ * Selects the next page
*/
- defaults(){
- this.expanded = this.expanded || {};
-
- this.options = angular.extend(angular.
- copy(TableDefaults), this.options);
+ nextPage(){
+ this.selectPage(++this.page);
+ }
- angular.forEach(TableDefaults.paging, (v,k) => {
- if(!this.options.paging[k]){
- this.options.paging[k] = v;
- }
- });
+ /**
+ * Determines if the pager can go previous
+ * @return {boolean}
+ */
+ canPrevious(){
+ return this.page > 1;
+ }
- if(this.options.selectable && this.options.multiSelect){
- this.selected = this.selected || [];
- }
+ /**
+ * Determines if the pager can go forward
+ * @return {boolean}
+ */
+ canNext(){
+ return this.page < this.totalPages;
}
/**
- * On init or when a column is added, we need to
- * make sure all the columns added have the correct
- * defaults applied.
+ * Gets the page set given the current page
+ * @param {int} page
*/
- transposeColumnDefaults(){
- for(var i=0, len = this.options.columns.length; i < len; i++) {
- var column = this.options.columns[i];
- column.$id = ObjectId();
+ getPages(page) {
+ var pages = [],
+ startPage = 1,
+ endPage = this.totalPages,
+ maxSize = 5,
+ isMaxSized = maxSize < this.totalPages;
- angular.forEach(ColumnDefaults, (v,k) => {
- if(!column.hasOwnProperty(k)){
- column[k] = v;
- }
+ if (isMaxSized) {
+ startPage = ((Math.ceil(page / maxSize) - 1) * maxSize) + 1;
+ endPage = Math.min(startPage + maxSize - 1, this.totalPages);
+ }
+
+ for (var number = startPage; number <= endPage; number++) {
+ pages.push({
+ number: number,
+ text: number,
+ active: number === page
});
+ }
- if(column.name && !column.prop){
- column.prop = CamelCase(column.name);
+ /*
+ if (isMaxSized) {
+ if (startPage > 1) {
+ pages.unshift({
+ number: startPage - 1,
+ text: '...'
+ });
}
- this.options.columns[i] = column;
+ if (endPage < this.totalPages) {
+ pages.push({
+ number: endPage + 1,
+ text: '...'
+ });
+ }
}
- }
+ */
- /**
- * Calculate column groups and widths
- */
- calculateColumns(){
- var columns = this.options.columns;
- this.columnsByPin = ColumnsByPin(columns);
- this.columnWidths = ColumnGroupWidths(this.columnsByPin, columns);
+ this.pages = pages;
}
- /**
- * Returns the css classes for the data table.
- * @return {style object}
- */
- tableCss(){
- return {
- 'fixed': this.options.scrollbarV,
- 'selectable': this.options.selectable,
- 'checkboxable': this.options.checkboxSelection
- };
- }
+}
+
+function PagerDirective(){
+ return {
+ restrict: 'E',
+ controller: PagerController,
+ controllerAs: 'pager',
+ scope: true,
+ bindToController: {
+ page: '=',
+ size: '=',
+ count: '=',
+ onPage: '&'
+ },
+ template:
+ ``,
+ replace: true
+ };
+}
+
+/**
+ * Popover Directive
+ * @param {object} $q
+ * @param {function} $timeout
+ * @param {function} $templateCache
+ * @param {function} $compile
+ * @param {function} PopoverRegistry
+ * @param {function} $animate
+ */
+function PopoverDirective($q, $timeout, $templateCache, $compile, PopoverRegistry, PositionHelper, $animate){
/**
- * Adjusts the column widths to handle greed/etc.
- * @param {int} forceIdx
+ * Loads a template from the template cache
+ * @param {string} template
+ * @param {boolean} plain
+ * @return {object} html template
*/
- adjustColumns(forceIdx){
- var width = this.options.internal.innerWidth - this.options.internal.scrollBarWidth;
+ function loadTemplate(template, plain) {
+ if (!template) {
+ return '';
+ }
- if(this.options.columnMode === 'force'){
- ForceFillColumnWidths(this.options.columns, width, forceIdx);
- } else if(this.options.columnMode === 'flex') {
- AdjustColumnWidths(this.options.columns, width);
+ if (angular$1.isString(template) && plain) {
+ return template;
}
+
+ return $templateCache.get(template) || $http.get(template, { cache : true });
}
/**
- * Calculates the page size given the height * row height.
- * @return {[type]}
+ * Determines a boolean given a value
+ * @param {object} value
+ * @return {boolean}
*/
- calculatePageSize(){
- this.options.paging.size = Math.ceil(
- this.options.internal.bodyHeight / this.options.rowHeight) + 1;
+ function toBoolean(value) {
+ if (value && value.length !== 0) {
+ var v = ("" + value).toLowerCase();
+ value = (v == 'true');
+ } else {
+ value = false;
+ }
+ return value;
}
- /**
- * Sorts the values of the grid for client side sorting.
- */
- onSorted(){
- if(!this.rows) return;
+ return {
+ restrict: 'A',
+ scope: true,
+ replace: false,
+ link: function ($scope, $element, $attributes) {
+ $scope.popover = null;
+ $scope.popoverId = Date.now();
+
+ $scope.options = {
+ text: $attributes.popoverText,
+ template: $attributes.popoverTemplate,
+ plain: toBoolean($attributes.popoverPlain || false),
+ placement: $attributes.popoverPlacement || 'right',
+ alignment: $attributes.popoverAlignment || 'center',
+ group: $attributes.popoverGroup,
+ spacing: parseInt($attributes.popoverSpacing) || 0,
+ showCaret: toBoolean($attributes.popoverPlain || false)
+ };
- // return all sorted column, in the same order in which they were sorted
- var sorts = this.options.columns
- .filter((c) => {
- return c.sort;
- })
- .sort((a, b) => {
- // sort the columns with lower sortPriority order first
- if (a.sortPriority && b.sortPriority){
- if (a.sortPriority > b.sortPriority) return 1;
- if (a.sortPriority < b.sortPriority) return -1;
- } else if (a.sortPriority){
- return -1;
- } else if (b.sortPriority){
- return 1;
+ // attach exit and enter events to element
+ $element.off('mouseenter', display);
+ $element.on('mouseenter', display);
+ $element.off('mouseleave', mouseOut);
+ $element.on('mouseleave', mouseOut);
+
+ function mouseOut(){
+ $scope.exitTimeout = $timeout(remove, 500);
+ }
+
+ /**
+ * Displays the popover on the page
+ */
+ function display(){
+ // Cancel exit timeout
+ $timeout.cancel($scope.exitTimeout);
+
+ var elm = document.getElementById(`#${$scope.popoverId}`);
+ if ($scope.popover && elm) return;
+
+ // remove other popovers from the same group
+ if ($scope.options.group){
+ PopoverRegistry.removeGroup($scope.options.group, $scope.popoverId);
}
- return 0;
- })
- .map((c, i) => {
- // update sortPriority
- c.sortPriority = i + 1;
- return c;
- });
+ if ($scope.options.text && !$scope.options.template){
+ $scope.popover = angular$1.element(`
`);
- if(sorts.length){
- this.onSort({sorts: sorts});
+ $scope.popover.html($scope.options.text);
+ angular$1.element(document.body).append($scope.popover);
+ positionPopover($element, $scope.popover, $scope.options);
+ PopoverRegistry.add($scope.popoverId, {element: $element, popover: $scope.popover, group: $scope.options.group});
- if (this.options.onSort){
- this.options.onSort(sorts);
+ } else {
+ $q.when(loadTemplate($scope.options.template, $scope.options.plain)).then(function(template) {
+ if (!angular$1.isString(template)) {
+ if (template.data && angular$1.isString(template.data)){
+ template = template.data;
+ } else {
+ template = '';
+ }
+ }
+
+ $scope.popover = angular$1.element(`
`);
+
+ $scope.popover.html(template);
+ $compile($scope.popover)($scope);
+ angular$1.element(document.body).append($scope.popover);
+ positionPopover($element, $scope.popover, $scope.options);
+
+ // attach exit and enter events to popover
+ $scope.popover.off('mouseleave', mouseOut);
+ $scope.popover.on('mouseleave', mouseOut);
+ $scope.popover.on('mouseenter', function(){
+ $timeout.cancel($scope.exitTimeout);
+ });
+
+ PopoverRegistry.add($scope.popoverId, {
+ element: $element,
+ popover: $scope.popover,
+ group: $scope.options.group
+ });
+ });
+ }
}
- var clientSorts = [];
- for(var i=0, len=sorts.length; i < len; i++) {
- var c = sorts[i];
- if(c.comparator !== false){
- var dir = c.sort === 'asc' ? '' : '-';
- if (c.sortBy !== undefined) {
- clientSorts.push(dir + c.sortBy);
- } else {
- clientSorts.push(dir + c.prop);
- }
+ /**
+ * Removes the template from the registry and page
+ */
+ function remove(){
+ if ($scope.popover){
+ $scope.popover.remove();
}
+
+ $scope.popover = undefined;
+ PopoverRegistry.remove($scope.popoverId);
}
- if(clientSorts.length){
- // todo: more ideal to just resort vs splice and repush
- // but wasn't responding to this change ...
- var sortedValues = this.$filter('orderBy')(this.rows, clientSorts);
- this.rows.splice(0, this.rows.length);
- this.rows.push(...sortedValues);
+ /**
+ * Positions the popover
+ * @param {object} triggerElement
+ * @param {object} popover
+ * @param {object} options
+ */
+ function positionPopover(triggerElement, popover, options){
+ $timeout(function(){
+ var elDimensions = triggerElement[0].getBoundingClientRect(),
+ popoverDimensions = popover[0].getBoundingClientRect(),
+ top, left;
+
+ if (options.placement === 'right'){
+ left = elDimensions.left + elDimensions.width + options.spacing;
+ top = PositionHelper.calculateVerticalAlignment(elDimensions,
+ popoverDimensions, options.alignment);
+ }
+ if (options.placement === 'left'){
+ left = elDimensions.left - popoverDimensions.width - options.spacing;
+ top = PositionHelper.calculateVerticalAlignment(elDimensions,
+ popoverDimensions, options.alignment);
+ }
+ if (options.placement === 'top'){
+ top = elDimensions.top - popoverDimensions.height - options.spacing;
+ left = PositionHelper.calculateHorizontalAlignment(elDimensions,
+ popoverDimensions, options.alignment);
+ }
+ if (options.placement === 'bottom'){
+ top = elDimensions.top + elDimensions.height + options.spacing;
+ left = PositionHelper.calculateHorizontalAlignment(elDimensions,
+ popoverDimensions, options.alignment);
+ }
+
+ popover.css({
+ top: top + 'px',
+ left: left + 'px'
+ });
+
+ if($scope.options.showCaret){
+ addCaret($scope.popover, elDimensions, popoverDimensions);
+ }
+
+ $animate.addClass($scope.popover, 'popover-animation');
+ }, 50);
}
- }
- this.options.internal.setYOffset(0);
+ /**
+ * Adds a caret and positions it relatively to the popover
+ * @param {object} popoverEl
+ * @param {object} elDimensions
+ * @param {object} popoverDimensions
+ */
+ function addCaret(popoverEl, elDimensions, popoverDimensions){
+ var caret = angular$1.element(` `);
+ popoverEl.append(caret);
+ var caretDimensions = caret[0].getBoundingClientRect();
+
+ var left, top;
+ if ($scope.options.placement === 'right'){
+ left = -6;
+ top = PositionHelper.calculateVerticalCaret(elDimensions,
+ popoverDimensions, caretDimensions, $scope.options.alignment);
+ }
+ if ($scope.options.placement === 'left'){
+ left = popoverDimensions.width - 2;
+ top = PositionHelper.calculateVerticalCaret(elDimensions,
+ popoverDimensions, caretDimensions, $scope.options.alignment);
+ }
+ if ($scope.options.placement === 'top'){
+ top = popoverDimensions.height - 5;
+ left = PositionHelper.calculateHorizontalCaret(elDimensions,
+ popoverDimensions, caretDimensions, $scope.options.alignment);
+ }
+
+ if ($scope.options.placement === 'bottom'){
+ top = -8;
+ left = PositionHelper.calculateHorizontalCaret(elDimensions,
+ popoverDimensions, caretDimensions, $scope.options.alignment);
+ }
+
+ caret.css({
+ top: top + 'px',
+ left: left + 'px'
+ });
+ }
+
+ }
}
+}
- /**
- * Invoked when a tree is collasped/expanded
- * @param {row model}
- * @param {cell model}
- */
- onTreeToggled(row, cell){
- this.onTreeToggle({
- row: row,
- cell: cell
+/**
+ * Registering to deal with popovers
+ * @param {function} $animate
+ */
+function PopoverRegistry($animate){
+ var popovers = {};
+ this.add = function(id, object){
+ popovers[id] = object;
+ };
+ this.find = function(id){
+ popovers[id];
+ };
+ this.remove = function(id){
+ delete popovers[id];
+ };
+ this.removeGroup = function(group, currentId){
+ angular.forEach(popovers, function(popoverOb, id){
+ if (id === currentId) return;
+
+ if (popoverOb.group && popoverOb.group === group){
+ $animate.removeClass(popoverOb.popover, 'sw-popover-animate').then(() => {
+ popoverOb.popover.remove();
+ delete popovers[id];
+ });
+ }
});
- }
+ };
+}
- /**
- * Invoked when the body triggers a page change.
- * @param {offset}
- * @param {size}
- */
- onBodyPage(offset, size){
- this.onPage({
- offset: offset,
- size: size
- });
- }
+/**
+ * Position helper for the popover directive.
+ */
+function PositionHelper(){
+ return {
- /**
- * Invoked when the footer triggers a page change.
- * @param {offset}
- * @param {size}
- */
- onFooterPage(offset, size){
- var pageBlockSize = this.options.rowHeight * size,
- offsetY = pageBlockSize * offset;
+ calculateVerticalAlignment: function(elDimensions, popoverDimensions, alignment){
+ if (alignment === 'top'){
+ return elDimensions.top;
+ }
+ if (alignment === 'bottom'){
+ return elDimensions.top + elDimensions.height - popoverDimensions.height;
+ }
+ if (alignment === 'center'){
+ return elDimensions.top + elDimensions.height/2 - popoverDimensions.height/2;
+ }
+ },
- this.options.internal.setYOffset(offsetY);
- }
+ calculateVerticalCaret: function(elDimensions, popoverDimensions, caretDimensions, alignment){
+ if (alignment === 'top'){
+ return elDimensions.height/2 - caretDimensions.height/2 - 1;
+ }
+ if (alignment === 'bottom'){
+ return popoverDimensions.height - elDimensions.height/2 - caretDimensions.height/2 - 1;
+ }
+ if (alignment === 'center'){
+ return popoverDimensions.height/2 - caretDimensions.height/2 - 1;
+ }
+ },
- /**
- * Invoked when the header checkbox directive has changed.
- */
- onHeaderCheckboxChange(){
- if(this.rows){
- var matches = this.selected.length === this.rows.length;
- this.selected.splice(0, this.selected.length);
+ calculateHorizontalCaret: function(elDimensions, popoverDimensions, caretDimensions, alignment){
+ if (alignment === 'left'){
+ return elDimensions.width/2 - caretDimensions.height/2 - 1;
+ }
+ if (alignment === 'right'){
+ return popoverDimensions.width - elDimensions.width/2 - caretDimensions.height/2 - 1;
+ }
+ if (alignment === 'center'){
+ return popoverDimensions.width/2 - caretDimensions.height/2 - 1;
+ }
+ },
- if(!matches){
- this.selected.push(...this.rows);
+ calculateHorizontalAlignment: function(elDimensions, popoverDimensions, alignment){
+ if (alignment === 'left'){
+ return elDimensions.left;
+ }
+ if (alignment === 'right'){
+ return elDimensions.left + elDimensions.width - popoverDimensions.width;
+ }
+ if (alignment === 'center'){
+ return elDimensions.left + elDimensions.width/2 - popoverDimensions.width/2;
}
}
- }
- /**
- * Returns if all the rows are selected
- * @return {Boolean} if all selected
- */
- isAllRowsSelected(){
- if(this.rows) return false;
- return this.selected.length === this.rows.length;
}
+}
- /**
- * Occurs when a header directive triggered a resize event
- * @param {object} column
- * @param {int} width
- */
- onResized(column, width){
- var idx =this.options.columns.indexOf(column);
- if(idx > -1){
- var column = this.options.columns[idx];
- column.width = width;
- column.canAutoResize = false;
+var popover = angular$1
+ .module('dt.popover', [])
+ .service('PopoverRegistry', PopoverRegistry)
+ .factory('PositionHelper', PositionHelper)
+ .directive('popover', PopoverDirective);
- this.adjustColumns(idx);
- this.calculateColumns();
- }
+class MenuController{
- if (this.onColumnResize){
- this.onColumnResize({
- column: column,
- width: width
- });
- }
+ /*@ngInject*/
+ constructor($scope, $timeout){
+ this.$scope = $scope;
}
- /**
- * Occurs when a row was selected
- * @param {object} rows
- */
- onSelected(rows){
- this.onSelect({
- rows: rows
+ getColumnIndex(model){
+ return this.$scope.current.findIndex((col) => {
+ return model.name == col.name;
});
}
- /**
- * Occurs when a row was click but may not be selected.
- * @param {object} row
- */
- onRowClicked(row){
- this.onRowClick({
- row: row
- });
+ isChecked(model){
+ return this.getColumnIndex(model) > -1;
}
- /**
- * Occurs when a row was double click but may not be selected.
- * @param {object} row
- */
- onRowDblClicked(row){
- this.onRowDblClick({
- row: row
- });
+ onCheck(model){
+ var idx = this.getColumnIndex(model);
+ if(idx === -1){
+ this.$scope.current.push(model);
+ } else {
+ this.$scope.current.splice(idx, 1);
+ }
}
-
+
}
-function DataTableDirective($window, $timeout, $parse){
+function MenuDirective(){
return {
restrict: 'E',
- replace: true,
- controller: DataTableController,
- scope: true,
- bindToController: {
- options: '=',
- rows: '=',
- selected: '=?',
- expanded: '=?',
- onSelect: '&',
- onSort: '&',
- onTreeToggle: '&',
- onPage: '&',
- onRowClick: '&',
- onRowDblClick: '&',
- onColumnResize: '&'
- },
- controllerAs: 'dt',
- template: function(element){
- // Gets the column nodes to transposes to column objects
- // http://stackoverflow.com/questions/30845397/angular-expressive-directive-design/30847609#30847609
- var columns = element[0].getElementsByTagName('column'),
- id = ObjectId();
- DataTableService.saveColumns(id, columns);
-
- return `
-
-
-
-
-
-
-
`
+ controller: 'MenuController',
+ controllerAs: 'dtm',
+ scope: {
+ current: '=',
+ available: '='
},
- compile: function(tElem, tAttrs){
- return {
- pre: function($scope, $elm, $attrs, ctrl){
- DataTableService.buildColumns($scope, $parse);
+ template:
+ ``
+ };
+}
- // Check and see if we had expressive columns
- // and if so, lets use those
- var id = $elm.attr('data-column-id'),
- columns = DataTableService.columns[id];
- if (columns) {
- ctrl.options.columns = columns;
- }
+class DropdownController{
+ /*@ngInject*/
+ constructor($scope){
+ $scope.open = false;
+ }
- ctrl.transposeColumnDefaults();
- ctrl.options.internal.scrollBarWidth = ScrollbarWidth();
+ toggle(scope){
+ scope.open = !scope.open;
+ }
+}
- /**
- * Invoked on init of control or when the window is resized;
- */
- function resize() {
- var rect = $elm[0].getBoundingClientRect();
+function DropdownDirective($document, $timeout){
+ return {
+ restrict: 'C',
+ controller: 'DropdownController',
+ link: function($scope, $elm, $attrs) {
- ctrl.options.internal.innerWidth = Math.floor(rect.width);
+ function closeDropdown(ev){
+ if($elm[0].contains(ev.target) ) {
+ return;
+ }
- if (ctrl.options.scrollbarV) {
- var height = rect.height;
+ $timeout(() => {
+ $scope.open = false;
+ off();
+ });
+ }
- if (ctrl.options.headerHeight) {
- height = height - ctrl.options.headerHeight;
- }
+ function keydown(ev){
+ if (ev.which === 27) {
+ $timeout(() => {
+ $scope.open = false;
+ off();
+ });
+ }
+ }
- if (ctrl.options.footerHeight) {
- height = height - ctrl.options.footerHeight;
- }
+ function off(){
+ $document.unbind('click', closeDropdown);
+ $document.unbind('keydown', keydown);
+ }
- ctrl.options.internal.bodyHeight = height;
- ctrl.calculatePageSize();
- }
+ $scope.$watch('open', (newVal) => {
+ if(newVal){
+ $document.bind('click', closeDropdown);
+ $document.bind('keydown', keydown);
+ }
+ });
+
+ }
+ };
+}
- ctrl.adjustColumns();
- };
+function DropdownToggleDirective($timeout){
+ return {
+ restrict: 'C',
+ controller: 'DropdownController',
+ require: '?^dropdown',
+ link: function($scope, $elm, $attrs, ctrl) {
- $window.addEventListener('resize',
- throttle(() => {
- $timeout(resize);
- }));
+ function toggleClick(event) {
+ event.preventDefault();
+ $timeout(() => {
+ ctrl.toggle($scope);
+ });
+ }
- // When an item is hidden for example
- // in a tab with display none, the height
- // is not calculated correrctly. We need to watch
- // the visible attribute and resize if this occurs
- var checkVisibility = function() {
- var bounds = $elm[0].getBoundingClientRect(),
- visible = bounds.width && bounds.height;
- if (visible) resize();
- else $timeout(checkVisibility, 100);
- };
- checkVisibility();
+ function toggleDestroy(){
+ $elm.unbind('click', toggleClick);
+ }
- // add a loaded class to avoid flickering
- $elm.addClass('dt-loaded');
+ $elm.bind('click', toggleClick);
+ $scope.$on('$destroy', toggleDestroy);
+ }
+ };
+}
- // prevent memory leaks
- $scope.$on('$destroy', () => {
- angular.element($window).off('resize');
- });
- }
- };
+function DropdownMenuDirective($animate){
+ return {
+ restrict: 'C',
+ require: '?^dropdown',
+ link: function($scope, $elm, $attrs, ctrl) {
+ $scope.$watch('open', () => {
+ $animate[$scope.open ? 'addClass' : 'removeClass']($elm, 'ddm-open');
+ });
}
};
}
-var dataTable = angular
+var dropdown = angular$1
+ .module('dt.dropdown', [])
+ .controller('DropdownController', DropdownController)
+ .directive('dropdown', DropdownDirective)
+ .directive('dropdownToggle', DropdownToggleDirective)
+ .directive('dropdownMenu', DropdownMenuDirective);
+
+var menu = angular$1
+ .module('dt.menu', [ dropdown.name ])
+ .controller('MenuController', MenuController)
+ .directive('dtm', MenuDirective);
+
+var dataTable = angular$1
.module('data-table', [])
.directive('dtable', DataTableDirective)
.directive('resizable', ResizableDirective)
@@ -3080,4 +3560,4 @@ var dataTable = angular
.directive('dtFooter', FooterDirective)
.directive('dtPager', PagerDirective);
-export default dataTable;
\ No newline at end of file
+export { popover as dtPopover, menu as dtMenu };export default dataTable;
diff --git a/release/dataTable.js b/release/dataTable.js
index 10dc89c..9b978fb 100644
--- a/release/dataTable.js
+++ b/release/dataTable.js
@@ -6,34 +6,37 @@
*/
(function (global, factory) {
if (typeof define === "function" && define.amd) {
- define("DataTable", ["exports"], factory);
+ define("DataTable", ["exports", "angular"], factory);
} else if (typeof exports !== "undefined") {
- factory(exports);
+ factory(exports, require("angular"));
} else {
var mod = {
exports: {}
};
- factory(mod.exports);
+ factory(mod.exports, global.angular);
global.DataTable = mod.exports;
}
-})(this, function (exports) {
+})(this, function (exports, _angular) {
"use strict";
- DataTableDirective.$inject = ["$window", "$timeout", "$parse"];
- ResizableDirective.$inject = ["$document", "$timeout"];
- SortableDirective.$inject = ["$timeout"];
- HeaderDirective.$inject = ["$timeout"];
- HeaderCellDirective.$inject = ["$compile"];
- BodyDirective.$inject = ["$timeout"];
- ScrollerDirective.$inject = ["$timeout", "$rootScope"];
- CellDirective.$inject = ["$rootScope", "$compile", "$log", "$timeout"];
Object.defineProperty(exports, "__esModule", {
value: true
});
+ exports.dtMenu = exports.dtPopover = undefined;
+
+ var _angular2 = _interopRequireDefault(_angular);
+
+ function _interopRequireDefault(obj) {
+ return obj && obj.__esModule ? obj : {
+ default: obj
+ };
+ }
function _toConsumableArray(arr) {
if (Array.isArray(arr)) {
- for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
+ for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {
+ arr2[i] = arr[i];
+ }
return arr2;
} else {
@@ -103,308 +106,289 @@
}
})();
- var PagerController = function () {
- PagerController.$inject = ["$scope"];
- function PagerController($scope) {
- var _this = this;
+ function ResizableDirective($document, $timeout) {
+ return {
+ restrict: 'A',
+ scope: {
+ isResizable: '=resizable',
+ minWidth: '=',
+ maxWidth: '=',
+ onResize: '&'
+ },
+ link: function link($scope, $element, $attrs) {
+ if ($scope.isResizable) {
+ $element.addClass('resizable');
+ }
- _classCallCheck(this, PagerController);
+ var handle = angular.element(" "),
+ parent = $element.parent(),
+ prevScreenX;
- $scope.$watch('pager.count', function (newVal) {
- _this.calcTotalPages(_this.size, _this.count);
- _this.getPages(_this.page || 1);
- });
+ handle.on('mousedown', function (event) {
+ if (!$element[0].classList.contains('resizable')) {
+ return false;
+ }
- $scope.$watch('pager.size', function (newVal) {
- _this.calcTotalPages(_this.size, _this.count);
- _this.getPages(_this.page || 1);
- });
+ event.stopPropagation();
+ event.preventDefault();
- $scope.$watch('pager.page', function (newVal) {
- if (newVal !== 0 && newVal <= _this.totalPages) {
- _this.getPages(newVal);
+ $document.on('mousemove', mousemove);
+ $document.on('mouseup', mouseup);
+ });
+
+ function mousemove(event) {
+ event = event.originalEvent || event;
+
+ var width = parent[0].clientWidth,
+ movementX = event.movementX || event.mozMovementX || event.screenX - prevScreenX,
+ newWidth = width + (movementX || 0);
+
+ prevScreenX = event.screenX;
+
+ if ((!$scope.minWidth || newWidth >= $scope.minWidth) && (!$scope.maxWidth || newWidth <= $scope.maxWidth)) {
+ parent.css({
+ width: newWidth + 'px'
+ });
+ }
}
- });
- this.getPages(this.page || 1);
- }
+ function mouseup() {
+ if ($scope.onResize) {
+ $timeout(function () {
+ var width = parent[0].clientWidth;
+ if (width < $scope.minWidth) {
+ width = $scope.minWidth;
+ }
+ $scope.onResize({ width: width });
+ });
+ }
- _createClass(PagerController, [{
- key: "calcTotalPages",
- value: function calcTotalPages(size, count) {
- var count = size < 1 ? 1 : Math.ceil(count / size);
- this.totalPages = Math.max(count || 0, 1);
- }
- }, {
- key: "selectPage",
- value: function selectPage(num) {
- if (num > 0 && num <= this.totalPages) {
- this.page = num;
- this.onPage({
- page: num
- });
+ $document.unbind('mousemove', mousemove);
+ $document.unbind('mouseup', mouseup);
}
+
+ $element.append(handle);
}
- }, {
- key: "prevPage",
- value: function prevPage() {
- if (this.page > 1) {
- this.selectPage(--this.page);
+ };
+ }
+
+ function SortableDirective($timeout) {
+ return {
+ restrict: 'A',
+ scope: {
+ isSortable: '=sortable',
+ onSortableSort: '&'
+ },
+ link: function link($scope, $element, $attrs) {
+ var rootEl = $element[0],
+ dragEl,
+ nextEl,
+ dropEl;
+
+ function isbefore(a, b) {
+ if (a.parentNode == b.parentNode) {
+ for (var cur = a; cur; cur = cur.previousSibling) {
+ if (cur === b) {
+ return true;
+ }
+ }
+ }
+ return false;
}
- }
- }, {
- key: "nextPage",
- value: function nextPage() {
- this.selectPage(++this.page);
- }
- }, {
- key: "canPrevious",
- value: function canPrevious() {
- return this.page > 1;
- }
- }, {
- key: "canNext",
- value: function canNext() {
- return this.page < this.totalPages;
- }
- }, {
- key: "getPages",
- value: function getPages(page) {
- var pages = [],
- startPage = 1,
- endPage = this.totalPages,
- maxSize = 5,
- isMaxSized = maxSize < this.totalPages;
- if (isMaxSized) {
- startPage = (Math.ceil(page / maxSize) - 1) * maxSize + 1;
- endPage = Math.min(startPage + maxSize - 1, this.totalPages);
+ function onDragEnter(e) {
+ var target = e.target;
+ if (isbefore(dragEl, target)) {
+ target.parentNode.insertBefore(dragEl, target);
+ } else if (target.nextSibling && target.hasAttribute('draggable')) {
+ target.parentNode.insertBefore(dragEl, target.nextSibling.nextSibling);
+ }
}
- for (var number = startPage; number <= endPage; number++) {
- pages.push({
- number: number,
- text: number,
- active: number === page
- });
+ function onDragEnd(evt) {
+ evt.preventDefault();
+
+ dragEl.classList.remove('dt-clone');
+
+ $element.off('dragend', onDragEnd);
+ $element.off('dragenter', onDragEnter);
+
+ if (nextEl !== dragEl.nextSibling) {
+ $scope.onSortableSort({
+ event: evt,
+ columnId: _angular2.default.element(dragEl).attr('data-id')
+ });
+ }
}
- this.pages = pages;
- }
- }]);
+ function onDragStart(evt) {
+ if (!$scope.isSortable) return false;
+ evt = evt.originalEvent || evt;
- return PagerController;
- }();
+ dragEl = evt.target;
+ nextEl = dragEl.nextSibling;
+ dragEl.classList.add('dt-clone');
- function PagerDirective() {
- return {
- restrict: 'E',
- controller: PagerController,
- controllerAs: 'pager',
- scope: true,
- bindToController: {
- page: '=',
- size: '=',
- count: '=',
- onPage: '&'
- },
- template: "",
- replace: true
+ evt.dataTransfer.effectAllowed = 'move';
+ evt.dataTransfer.setData('Text', dragEl.textContent);
+
+ $element.on('dragenter', onDragEnter);
+ $element.on('dragend', onDragEnd);
+ }
+
+ $element.on('dragstart', onDragStart);
+
+ $scope.$on('$destroy', function () {
+ $element.off('dragstart', onDragStart);
+ });
+ }
};
}
- var FooterController = function () {
- FooterController.$inject = ["$scope"];
- function FooterController($scope) {
- var _this2 = this;
+ var TableDefaults = {
+ scrollbarV: true,
- _classCallCheck(this, FooterController);
+ rowHeight: 30,
- this.page = this.paging.offset + 1;
- $scope.$watch('footer.paging.offset', function (newVal) {
- _this2.offsetChanged(newVal);
- });
- }
+ columnMode: 'standard',
- _createClass(FooterController, [{
- key: "offsetChanged",
- value: function offsetChanged(newVal) {
- this.page = newVal + 1;
- }
- }, {
- key: "onPaged",
- value: function onPaged(page) {
- this.paging.offset = page - 1;
- this.onPage({
- offset: this.paging.offset,
- size: this.paging.size
- });
- }
- }]);
+ loadingMessage: 'Loading...',
- return FooterController;
- }();
+ emptyMessage: 'No data to display',
- function FooterDirective() {
- return {
- restrict: 'E',
- controller: FooterController,
- controllerAs: 'footer',
- scope: true,
- bindToController: {
- paging: '=',
- onPage: '&'
- },
- template: "",
- replace: true
- };
- }
+ headerHeight: 30,
- var CellController = function () {
- function CellController() {
- _classCallCheck(this, CellController);
- }
+ footerHeight: 0,
- _createClass(CellController, [{
- key: "styles",
- value: function styles() {
- return {
- width: this.column.width + 'px',
- 'min-width': this.column.width + 'px'
- };
- }
- }, {
- key: "cellClass",
- value: function cellClass() {
- var style = {
- 'dt-tree-col': this.column.isTreeColumn
- };
+ paging: {
+ externalPaging: false,
- if (this.column.className) {
- style[this.column.className] = true;
- }
+ size: undefined,
- return style;
- }
- }, {
- key: "treeClass",
- value: function treeClass() {
- return {
- 'dt-tree-toggle': true,
- 'icon-right': !this.expanded,
- 'icon-down': this.expanded
- };
- }
- }, {
- key: "onTreeToggled",
- value: function onTreeToggled(evt) {
- evt.stopPropagation();
- this.expanded = !this.expanded;
- this.onTreeToggle({
- cell: {
- value: this.value,
- column: this.column,
- expanded: this.expanded
- }
- });
- }
- }, {
- key: "onCheckboxChanged",
- value: function onCheckboxChanged(event) {
- event.stopPropagation();
- this.onCheckboxChange({ $event: event });
- }
- }, {
- key: "getValue",
- value: function getValue() {
- var val = this.column.cellDataGetter ? this.column.cellDataGetter(this.value) : this.value;
+ count: 0,
- if (val === undefined || val === null) val = '';
- return val;
- }
- }]);
+ offset: 0,
- return CellController;
- }();
+ loadingIndicator: false
+ },
- function CellDirective($rootScope, $compile, $log, $timeout) {
- return {
- restrict: 'E',
- controller: CellController,
- scope: true,
- controllerAs: 'cell',
- bindToController: {
- options: '=',
- value: '=',
- selected: '=',
- column: '=',
- row: '=',
- expanded: '=',
- hasChildren: '=',
- onTreeToggle: '&',
- onCheckboxChange: '&'
- },
- template: "\n \n \n \n \n \n
",
- replace: true,
- compile: function compile() {
- return {
- pre: function pre($scope, $elm, $attrs, ctrl) {
- var content = angular.element($elm[0].querySelector('.dt-cell-content')),
- cellScope;
+ selectable: false,
- if (ctrl.column.template || ctrl.column.cellRenderer) {
- createCellScope();
- }
+ multiSelect: false,
- $scope.$watch('cell.row', function () {
- if (cellScope) {
- cellScope.$destroy();
+ checkboxSelection: false,
- createCellScope();
+ reorderable: true,
- cellScope.$cell = ctrl.value;
- cellScope.$row = ctrl.row;
- cellScope.$column = ctrl.column;
- cellScope.$$watchers = null;
- }
+ internal: {
+ offsetX: 0,
+ offsetY: 0,
+ innerWidth: 0,
+ bodyHeight: 300
+ }
- if (ctrl.column.template) {
- content.empty();
- var elm = angular.element("" + ctrl.column.template.trim() + " ");
- content.append($compile(elm)(cellScope));
- } else if (ctrl.column.cellRenderer) {
- content.empty();
- var elm = angular.element(ctrl.column.cellRenderer(cellScope, content));
- content.append($compile(elm)(cellScope));
- } else {
- content[0].innerHTML = ctrl.getValue();
- }
- }, true);
+ };
- function createCellScope() {
- cellScope = ctrl.options.$outer.$new(false);
- cellScope.getValue = ctrl.getValue;
- }
- }
- };
- }
+ var ColumnDefaults = {
+ frozenLeft: false,
+
+ frozenRight: false,
+
+ className: undefined,
+
+ headerClassName: undefined,
+
+ flexGrow: 0,
+
+ minWidth: 100,
+
+ maxWidth: undefined,
+
+ width: 150,
+
+ resizable: true,
+
+ comparator: undefined,
+
+ sortable: true,
+
+ sort: undefined,
+
+ sortBy: undefined,
+
+ headerRenderer: undefined,
+
+ cellRenderer: undefined,
+
+ cellDataGetter: undefined,
+
+ isTreeColumn: false,
+
+ isCheckboxColumn: false,
+
+ headerCheckbox: false,
+
+ canAutoResize: true
+
+ };
+
+ var requestAnimFrame = function () {
+ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {
+ window.setTimeout(callback, 1000 / 60);
};
+ }();
+
+ function ObjectId() {
+ var timestamp = (new Date().getTime() / 1000 | 0).toString(16);
+ return timestamp + 'xxxxxxxxxxxxxxxx'.replace(/[x]/g, function () {
+ return (Math.random() * 16 | 0).toString(16);
+ }).toLowerCase();
}
- var cache = {},
- testStyle = document.createElement('div').style;
+ function ColumnsByPin(cols) {
+ var ret = {
+ left: [],
+ center: [],
+ right: []
+ };
- var prefix = function () {
- var styles = window.getComputedStyle(document.documentElement, ''),
- pre = (Array.prototype.slice.call(styles).join('').match(/-(moz|webkit|ms)-/) || styles.OLink === '' && ['', 'o'])[1],
- dom = 'WebKit|Moz|MS|O'.match(new RegExp('(' + pre + ')', 'i'))[1];
+ for (var i = 0, len = cols.length; i < len; i++) {
+ var c = cols[i];
+ if (c.frozenLeft) {
+ ret.left.push(c);
+ } else if (c.frozenRight) {
+ ret.right.push(c);
+ } else {
+ ret.center.push(c);
+ }
+ }
+
+ return ret;
+ }
+
+ function ColumnGroupWidths(groups, all) {
return {
- dom: dom,
- lowercase: pre,
- css: '-' + pre + '-',
- js: pre[0].toUpperCase() + pre.substr(1)
+ left: ColumnTotalWidth(groups.left),
+ center: ColumnTotalWidth(groups.center),
+ right: ColumnTotalWidth(groups.right),
+ total: ColumnTotalWidth(all)
};
- }();
+ }
+
+ function DeepValueGetter(obj, path) {
+ if (!obj || !path) return obj;
+
+ var current = obj,
+ split = path.split('.');
+
+ if (split.length) {
+ for (var i = 0, len = split.length; i < len; i++) {
+ current = current[split[i]];
+ }
+ }
+
+ return current;
+ }
function CamelCase(str) {
str = str.replace(/[^a-zA-Z0-9 ]/g, " ");
@@ -419,2021 +403,2442 @@
return str;
}
- function GetVendorPrefixedName(property) {
- var name = CamelCase(property);
- if (!cache[name]) {
- if (testStyle[prefix.css + property] !== undefined) {
- cache[name] = prefix.css + property;
- } else if (testStyle[property] !== undefined) {
- cache[name] = property;
- }
- }
- return cache[name];
- }
+ function ScrollbarWidth() {
+ var outer = document.createElement("div");
+ outer.style.visibility = "hidden";
+ outer.style.width = "100px";
+ outer.style.msOverflowStyle = "scrollbar";
+ document.body.appendChild(outer);
- var transform = GetVendorPrefixedName('transform'),
- backfaceVisibility = GetVendorPrefixedName('backfaceVisibility'),
- hasCSSTransforms = !!GetVendorPrefixedName('transform'),
- hasCSS3DTransforms = !!GetVendorPrefixedName('perspective'),
- ua = window.navigator.userAgent,
- isSafari = /Safari\//.test(ua) && !/Chrome\//.test(ua);
+ var widthNoScroll = outer.offsetWidth;
+ outer.style.overflow = "scroll";
- function TranslateXY(styles, x, y) {
- if (hasCSSTransforms) {
- if (!isSafari && hasCSS3DTransforms) {
- styles[transform] = "translate3d(" + x + "px, " + y + "px, 0)";
- styles[backfaceVisibility] = 'hidden';
- } else {
- styles[CamelCase(transform)] = "translate(" + x + "px, " + y + "px)";
- }
- } else {
- styles.top = y + 'px';
- styles.left = x + 'px';
- }
- }
+ var inner = document.createElement("div");
+ inner.style.width = "100%";
+ outer.appendChild(inner);
- var GroupRowController = function () {
- function GroupRowController() {
- _classCallCheck(this, GroupRowController);
- }
+ var widthWithScroll = inner.offsetWidth;
+ outer.parentNode.removeChild(outer);
- _createClass(GroupRowController, [{
- key: "onGroupToggled",
- value: function onGroupToggled(evt) {
- evt.stopPropagation();
- this.onGroupToggle({
- group: this.row
- });
+ return widthNoScroll - widthWithScroll;
+ }
+
+ function NextSortDirection(sortType, currentSort) {
+ if (sortType === 'single') {
+ if (currentSort === 'asc') {
+ return 'desc';
+ } else {
+ return 'asc';
}
- }, {
- key: "treeClass",
- value: function treeClass() {
- return {
- 'dt-tree-toggle': true,
- 'icon-right': !this.expanded,
- 'icon-down': this.expanded
- };
+ } else {
+ if (!currentSort) {
+ return 'asc';
+ } else if (currentSort === 'asc') {
+ return 'desc';
+ } else if (currentSort === 'desc') {
+ return undefined;
}
- }]);
+ }
+ }
- return GroupRowController;
- }();
+ function ColumnTotalWidth(columns, prop) {
+ var totalWidth = 0;
- function GroupRowDirective() {
- return {
- restrict: 'E',
- controller: GroupRowController,
- controllerAs: 'group',
- bindToController: {
- row: '=',
- onGroupToggle: '&',
- expanded: '=',
- options: '='
- },
- scope: true,
- replace: true,
- template: "\n \n \n \n \n \n
",
- link: function link($scope, $elm, $attrs, ctrl) {
- TranslateXY($elm[0].style, 0, ctrl.row.$$index * ctrl.options.rowHeight);
+ columns.forEach(function (c) {
+ var has = prop && c[prop];
+ totalWidth = totalWidth + (has ? c[prop] : c.width);
+ });
- ctrl.options.internal.styleTranslator.register($scope.$index, $elm);
- }
- };
+ return totalWidth;
}
- function DeepValueGetter(obj, path) {
- if (!obj || !path) return obj;
+ function GetTotalFlexGrow(columns) {
+ var totalFlexGrow = 0;
- var current = obj,
- split = path.split('.');
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
- if (split.length) {
- for (var i = 0, len = split.length; i < len; i++) {
- current = current[split[i]];
+ try {
+ for (var _iterator = columns[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ var c = _step.value;
+
+ totalFlexGrow += c.flexGrow || 0;
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
}
}
- return current;
+ return totalFlexGrow;
}
- var RowController = function () {
- function RowController() {
- _classCallCheck(this, RowController);
- }
+ function AdjustColumnWidths(allColumns, expectedWidth) {
+ var columnsWidth = ColumnTotalWidth(allColumns),
+ totalFlexGrow = GetTotalFlexGrow(allColumns),
+ colsByGroup = ColumnsByPin(allColumns);
- _createClass(RowController, [{
- key: "getValue",
- value: function getValue(col) {
- if (!col.prop) return '';
- return DeepValueGetter(this.row, col.prop);
- }
- }, {
- key: "onTreeToggled",
- value: function onTreeToggled(cell) {
- this.onTreeToggle({
- cell: cell,
- row: this.row
- });
- }
- }, {
- key: "stylesByGroup",
- value: function stylesByGroup(group) {
- var styles = {
- width: this.columnWidths[group] + 'px'
- };
+ if (columnsWidth !== expectedWidth) {
+ ScaleColumns(colsByGroup, expectedWidth, totalFlexGrow);
+ }
+ }
- if (group === 'left') {
- TranslateXY(styles, this.options.internal.offsetX, 0);
- } else if (group === 'right') {
- var offset = (this.columnWidths.total - this.options.internal.innerWidth - this.options.internal.offsetX + this.options.internal.scrollBarWidth) * -1;
- TranslateXY(styles, offset, 0);
+ function ScaleColumns(colsByGroup, maxWidth, totalFlexGrow) {
+ _angular2.default.forEach(colsByGroup, function (cols) {
+ cols.forEach(function (column) {
+ if (!column.canAutoResize) {
+ maxWidth -= column.width;
+ totalFlexGrow -= column.flexGrow;
+ } else {
+ column.width = 0;
}
+ });
+ });
- return styles;
- }
- }, {
- key: "onCheckboxChanged",
- value: function onCheckboxChanged(ev) {
- this.onCheckboxChange({
- $event: ev,
- row: this.row
+ var hasMinWidth = {};
+ var remainingWidth = maxWidth;
+
+ var _loop = function _loop() {
+ var widthPerFlexPoint = remainingWidth / totalFlexGrow;
+ remainingWidth = 0;
+ _angular2.default.forEach(colsByGroup, function (cols) {
+ cols.forEach(function (column, i) {
+ if (column.canAutoResize && !hasMinWidth[i]) {
+ var newWidth = column.width + column.flexGrow * widthPerFlexPoint;
+ if (column.minWidth !== undefined && newWidth < column.minWidth) {
+ remainingWidth += newWidth - column.minWidth;
+ column.width = column.minWidth;
+ hasMinWidth[i] = true;
+ } else {
+ column.width = newWidth;
+ }
+ }
});
+ });
+ };
+
+ do {
+ _loop();
+ } while (remainingWidth !== 0);
+ }
+
+ function ForceFillColumnWidths(allColumns, expectedWidth, startIdx) {
+ var contentWidth = 0,
+ columnsToResize = startIdx > -1 ? allColumns.slice(startIdx, allColumns.length).filter(function (c) {
+ return c.canAutoResize;
+ }) : allColumns.filter(function (c) {
+ return c.canAutoResize;
+ });
+
+ allColumns.forEach(function (c) {
+ if (!c.canAutoResize) {
+ contentWidth += c.width;
+ } else {
+ contentWidth += c.$$oldWidth || c.width;
}
- }]);
+ });
- return RowController;
- }();
+ var remainingWidth = expectedWidth - contentWidth,
+ additionWidthPerColumn = remainingWidth / columnsToResize.length,
+ exceedsWindow = contentWidth > expectedWidth;
- function RowDirective() {
- return {
- restrict: 'E',
- controller: RowController,
- controllerAs: 'rowCtrl',
- scope: true,
- bindToController: {
- row: '=',
- columns: '=',
- columnWidths: '=',
- expanded: '=',
- selected: '=',
- hasChildren: '=',
- options: '=',
- onCheckboxChange: '&',
- onTreeToggle: '&'
- },
- link: function link($scope, $elm, $attrs, ctrl) {
- if (ctrl.row) {
- TranslateXY($elm[0].style, 0, ctrl.row.$$index * ctrl.options.rowHeight);
+ columnsToResize.forEach(function (column) {
+ if (exceedsWindow) {
+ column.width = column.$$oldWidth || column.width;
+ } else {
+ if (!column.$$oldWidth) {
+ column.$$oldWidth = column.width;
}
- ctrl.options.internal.styleTranslator.register($scope.$index, $elm);
- },
- template: "\n \n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
",
- replace: true
- };
+ var newSize = column.$$oldWidth + additionWidthPerColumn;
+ if (column.minWith && newSize < column.minWidth) {
+ column.width = column.minWidth;
+ } else if (column.maxWidth && newSize > column.maxWidth) {
+ column.width = column.maxWidth;
+ } else {
+ column.width = newSize;
+ }
+ }
+ });
}
- var KEYS = {
- BACKSPACE: 8,
- TAB: 9,
- RETURN: 13,
- ALT: 18,
- ESC: 27,
- SPACE: 32,
- PAGE_UP: 33,
- PAGE_DOWN: 34,
- END: 35,
- HOME: 36,
- LEFT: 37,
- UP: 38,
- RIGHT: 39,
- DOWN: 40,
- DELETE: 46,
- COMMA: 188,
- PERIOD: 190,
- A: 65,
- Z: 90,
- ZERO: 48,
- NUMPAD_0: 96,
- NUMPAD_9: 105
- };
+ var DataTableController = function () {
+ function DataTableController($scope, $filter, $log, $transclude) {
+ var _this = this;
- var SelectionController = function () {
- SelectionController.$inject = ["$scope"];
- function SelectionController($scope) {
- _classCallCheck(this, SelectionController);
+ _classCallCheck(this, DataTableController);
- this.body = $scope.body;
- this.options = $scope.body.options;
- this.selected = $scope.body.selected;
- }
+ Object.assign(this, {
+ $scope: $scope,
+ $filter: $filter,
+ $log: $log
+ });
- _createClass(SelectionController, [{
- key: "keyDown",
- value: function keyDown(ev, index, row) {
- if (KEYS[ev.keyCode]) {
- ev.preventDefault();
+ this.defaults();
+
+ this.options.$outer = $scope.$parent;
+
+ $scope.$watch('dt.options.columns', function (newVal, oldVal) {
+ _this.transposeColumnDefaults();
+
+ if (newVal.length !== oldVal.length) {
+ _this.adjustColumns();
}
- if (ev.keyCode === KEYS.DOWN) {
- var next = ev.target.nextElementSibling;
- if (next) {
- next.focus();
- }
- } else if (ev.keyCode === KEYS.UP) {
- var prev = ev.target.previousElementSibling;
- if (prev) {
- prev.focus();
+ _this.calculateColumns();
+ }, true);
+
+ var watch = $scope.$watch('dt.rows', function (newVal) {
+ if (newVal) {
+ watch();
+ _this.onSorted();
+ }
+ });
+ }
+
+ _createClass(DataTableController, [{
+ key: "defaults",
+ value: function defaults() {
+ var _this2 = this;
+
+ this.expanded = this.expanded || {};
+
+ this.options = _angular2.default.extend(_angular2.default.copy(TableDefaults), this.options);
+
+ _angular2.default.forEach(TableDefaults.paging, function (v, k) {
+ if (!_this2.options.paging[k]) {
+ _this2.options.paging[k] = v;
}
- } else if (ev.keyCode === KEYS.RETURN) {
- this.selectRow(index, row);
+ });
+
+ if (this.options.selectable && this.options.multiSelect) {
+ this.selected = this.selected || [];
}
}
}, {
- key: "rowClicked",
- value: function rowClicked(event, index, row) {
- if (!this.options.checkboxSelection) {
- this.selectRow(event, index, row);
- }
+ key: "transposeColumnDefaults",
+ value: function transposeColumnDefaults() {
+ for (var i = 0, len = this.options.columns.length; i < len; i++) {
+ var column = this.options.columns[i];
+ column.$id = ObjectId();
- this.body.onRowClick({ row: row });
+ _angular2.default.forEach(ColumnDefaults, function (v, k) {
+ if (!column.hasOwnProperty(k)) {
+ column[k] = v;
+ }
+ });
+
+ if (column.name && !column.prop) {
+ column.prop = CamelCase(column.name);
+ }
+
+ this.options.columns[i] = column;
+ }
}
}, {
- key: "rowDblClicked",
- value: function rowDblClicked(event, index, row) {
- if (!this.options.checkboxSelection) {
- event.preventDefault();
- this.selectRow(event, index, row);
- }
-
- this.body.onRowDblClick({ row: row });
+ key: "calculateColumns",
+ value: function calculateColumns() {
+ var columns = this.options.columns;
+ this.columnsByPin = ColumnsByPin(columns);
+ this.columnWidths = ColumnGroupWidths(this.columnsByPin, columns);
}
}, {
- key: "onCheckboxChange",
- value: function onCheckboxChange(event, index, row) {
- this.selectRow(event, index, row);
+ key: "tableCss",
+ value: function tableCss() {
+ return {
+ 'fixed': this.options.scrollbarV,
+ 'selectable': this.options.selectable,
+ 'checkboxable': this.options.checkboxSelection
+ };
}
}, {
- key: "selectRow",
- value: function selectRow(event, index, row) {
- if (this.options.selectable) {
- if (this.options.multiSelect) {
- var isCtrlKeyDown = event.ctrlKey || event.metaKey,
- isShiftKeyDown = event.shiftKey;
+ key: "adjustColumns",
+ value: function adjustColumns(forceIdx) {
+ var width = this.options.internal.innerWidth - this.options.internal.scrollBarWidth;
- if (isShiftKeyDown) {
- this.selectRowsBetween(index, row);
- } else {
- var idx = this.selected.indexOf(row);
- if (idx > -1) {
- this.selected.splice(idx, 1);
- } else {
- if (this.options.multiSelectOnShift && this.selected.length === 1) {
- this.selected.splice(0, 1);
- }
- this.selected.push(row);
- this.body.onSelect({ rows: [row] });
- }
- }
- this.prevIndex = index;
- } else {
- this.selected = row;
- this.body.onSelect({ rows: [row] });
- }
+ if (this.options.columnMode === 'force') {
+ ForceFillColumnWidths(this.options.columns, width, forceIdx);
+ } else if (this.options.columnMode === 'flex') {
+ AdjustColumnWidths(this.options.columns, width);
}
}
}, {
- key: "selectRowsBetween",
- value: function selectRowsBetween(index) {
- var reverse = index < this.prevIndex,
- selecteds = [];
-
- for (var i = 0, len = this.body.rows.length; i < len; i++) {
- var row = this.body.rows[i],
- greater = i >= this.prevIndex && i <= index,
- lesser = i <= this.prevIndex && i >= index;
+ key: "calculatePageSize",
+ value: function calculatePageSize() {
+ this.options.paging.size = Math.ceil(this.options.internal.bodyHeight / this.options.rowHeight) + 1;
+ }
+ }, {
+ key: "onSorted",
+ value: function onSorted() {
+ if (!this.rows) return;
- var range = {};
- if (reverse) {
- range = {
- start: index,
- end: this.prevIndex - index
- };
- } else {
- range = {
- start: this.prevIndex,
- end: index + 1
- };
+ var sorts = this.options.columns.filter(function (c) {
+ return c.sort;
+ }).sort(function (a, b) {
+ if (a.sortPriority && b.sortPriority) {
+ if (a.sortPriority > b.sortPriority) return 1;
+ if (a.sortPriority < b.sortPriority) return -1;
+ } else if (a.sortPriority) {
+ return -1;
+ } else if (b.sortPriority) {
+ return 1;
}
- if (reverse && lesser || !reverse && greater) {
- var idx = this.selected.indexOf(row);
+ return 0;
+ }).map(function (c, i) {
+ c.sortPriority = i + 1;
+ return c;
+ });
- if (reverse && idx > -1) {
- this.selected.splice(idx, 1);
- continue;
- }
+ if (sorts.length) {
+ this.onSort({ sorts: sorts });
- if (i >= range.start && i < range.end) {
- if (idx === -1) {
- this.selected.push(row);
- selecteds.push(row);
+ if (this.options.onSort) {
+ this.options.onSort(sorts);
+ }
+
+ var clientSorts = [];
+ for (var i = 0, len = sorts.length; i < len; i++) {
+ var c = sorts[i];
+ if (c.comparator !== false) {
+ var dir = c.sort === 'asc' ? '' : '-';
+ if (c.sortBy !== undefined) {
+ clientSorts.push(dir + c.sortBy);
+ } else {
+ clientSorts.push(dir + c.prop);
}
}
}
+
+ if (clientSorts.length) {
+ var _rows;
+
+ var sortedValues = this.$filter('orderBy')(this.rows, clientSorts);
+ this.rows.splice(0, this.rows.length);
+ (_rows = this.rows).push.apply(_rows, _toConsumableArray(sortedValues));
+ }
}
- this.body.onSelect({ rows: selecteds });
+ this.options.internal.setYOffset(0);
}
- }]);
-
- return SelectionController;
- }();
+ }, {
+ key: "onTreeToggled",
+ value: function onTreeToggled(row, cell) {
+ this.onTreeToggle({
+ row: row,
+ cell: cell
+ });
+ }
+ }, {
+ key: "onBodyPage",
+ value: function onBodyPage(offset, size) {
+ this.onPage({
+ offset: offset,
+ size: size
+ });
+ }
+ }, {
+ key: "onFooterPage",
+ value: function onFooterPage(offset, size) {
+ var pageBlockSize = this.options.rowHeight * size,
+ offsetY = pageBlockSize * offset;
- function SelectionDirective() {
- return {
- controller: SelectionController,
- restrict: 'A',
- require: '^dtBody',
- controllerAs: 'selCtrl'
- };
- }
-
- var requestAnimFrame = function () {
- return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {
- window.setTimeout(callback, 1000 / 60);
- };
- }();
-
- var StyleTranslator = function () {
- function StyleTranslator(height) {
- _classCallCheck(this, StyleTranslator);
+ this.options.internal.setYOffset(offsetY);
+ }
+ }, {
+ key: "onHeaderCheckboxChange",
+ value: function onHeaderCheckboxChange() {
+ if (this.rows) {
+ var matches = this.selected.length === this.rows.length;
+ this.selected.splice(0, this.selected.length);
- this.height = height;
- this.map = new Map();
- }
+ if (!matches) {
+ var _selected;
- _createClass(StyleTranslator, [{
- key: "update",
- value: function update(rows) {
- var n = 0;
- while (n <= this.map.size) {
- var dom = this.map.get(n);
- var model = rows[n];
- if (dom && model) {
- TranslateXY(dom[0].style, 0, model.$$index * this.height);
+ (_selected = this.selected).push.apply(_selected, _toConsumableArray(this.rows));
}
- n++;
}
}
}, {
- key: "register",
- value: function register(idx, dom) {
- this.map.set(idx, dom);
+ key: "isAllRowsSelected",
+ value: function isAllRowsSelected() {
+ if (this.rows) return false;
+ return this.selected.length === this.rows.length;
}
- }]);
-
- return StyleTranslator;
- }();
-
- function ScrollerDirective($timeout, $rootScope) {
- return {
- restrict: 'E',
- require: '^dtBody',
- transclude: true,
- replace: true,
- template: "
",
- link: function link($scope, $elm, $attrs, ctrl) {
- var ticking = false,
- lastScrollY = 0,
- lastScrollX = 0,
- parent = $elm.parent();
-
- ctrl.options.internal.styleTranslator = new StyleTranslator(ctrl.options.rowHeight);
-
- ctrl.options.internal.setYOffset = function (offsetY) {
- parent[0].scrollTop = offsetY;
- };
-
- function update() {
- ctrl.options.internal.offsetY = lastScrollY;
- ctrl.options.internal.offsetX = lastScrollX;
- ctrl.updatePage();
-
- if (ctrl.options.scrollbarV) {
- ctrl.getRows();
- }
-
- ctrl.options.$outer.$digest();
-
- ticking = false;
- };
+ }, {
+ key: "onResized",
+ value: function onResized(column, width) {
+ var idx = this.options.columns.indexOf(column);
+ if (idx > -1) {
+ var column = this.options.columns[idx];
+ column.width = width;
+ column.canAutoResize = false;
- function requestTick() {
- if (!ticking) {
- requestAnimFrame(update);
- ticking = true;
- }
- };
+ this.adjustColumns(idx);
+ this.calculateColumns();
+ }
- parent.on('scroll', function (ev) {
- lastScrollY = this.scrollTop;
- lastScrollX = this.scrollLeft;
- requestTick();
+ if (this.onColumnResize) {
+ this.onColumnResize({
+ column: column,
+ width: width
+ });
+ }
+ }
+ }, {
+ key: "onSelected",
+ value: function onSelected(rows) {
+ this.onSelect({
+ rows: rows
});
-
- $scope.$on('$destroy', function () {
- parent.off('scroll');
+ }
+ }, {
+ key: "onRowClicked",
+ value: function onRowClicked(row) {
+ this.onRowClick({
+ row: row
});
+ }
+ }, {
+ key: "onRowDblClicked",
+ value: function onRowDblClicked(row) {
+ this.onRowDblClick({
+ row: row
+ });
+ }
+ }]);
- $scope.scrollerStyles = function () {
- if (ctrl.options.scrollbarV) {
- return {
- height: ctrl.count * ctrl.options.rowHeight + 'px'
- };
- }
- };
+ return DataTableController;
+ }();
+
+ function throttle(func, wait, options) {
+ var context, args, result;
+ var timeout = null;
+ var previous = 0;
+ options || (options = {});
+ var later = function later() {
+ previous = options.leading === false ? 0 : new Date();
+ timeout = null;
+ result = func.apply(context, args);
+ };
+ return function () {
+ var now = new Date();
+ if (!previous && options.leading === false) previous = now;
+ var remaining = wait - (now - previous);
+ context = this;
+ args = arguments;
+ if (remaining <= 0) {
+ clearTimeout(timeout);
+ timeout = null;
+ previous = now;
+ result = func.apply(context, args);
+ } else if (!timeout && options.trailing !== false) {
+ timeout = setTimeout(later, remaining);
}
+ return result;
};
}
- var BodyController = function () {
- BodyController.$inject = ["$scope", "$timeout"];
- function BodyController($scope, $timeout) {
- var _this3 = this;
-
- _classCallCheck(this, BodyController);
+ var DataTableService = {
+ columns: {},
+ dTables: {},
- this.$scope = $scope;
- this.tempRows = [];
+ saveColumns: function saveColumns(id, columnElms) {
+ if (columnElms && columnElms.length) {
+ var columnsArray = [].slice.call(columnElms);
+ this.dTables[id] = columnsArray;
+ }
+ },
+ buildColumns: function buildColumns(scope, parse) {
+ var _this3 = this;
- this.treeColumn = this.options.columns.find(function (c) {
- return c.isTreeColumn;
- });
+ _angular2.default.forEach(this.dTables, function (columnElms, id) {
+ _this3.columns[id] = [];
- this.groupColumn = this.options.columns.find(function (c) {
- return c.group;
- });
+ _angular2.default.forEach(columnElms, function (c) {
+ var column = {};
- $scope.$watchCollection('body.rows', this.rowsUpdated.bind(this));
+ var visible = true;
- if (this.options.scrollbarV || !this.options.scrollbarV && this.options.paging.externalPaging) {
- var sized = false;
- $scope.$watch('body.options.paging.size', function (newVal, oldVal) {
- if (!sized || newVal > oldVal) {
- _this3.getRows();
- sized = true;
- }
- });
+ _angular2.default.forEach(c.attributes, function (attr) {
+ var attrName = CamelCase(attr.name);
- $scope.$watch('body.options.paging.count', function (count) {
- _this3.count = count;
- _this3.updatePage();
- });
+ switch (attrName) {
+ case 'class':
+ column.className = attr.value;
+ break;
+ case 'name':
+ case 'prop':
+ column[attrName] = attr.value;
+ break;
+ case 'headerRenderer':
+ case 'cellRenderer':
+ case 'cellDataGetter':
+ column[attrName] = parse(attr.value);
+ break;
+ case 'visible':
+ visible = parse(attr.value)(scope);
+ break;
+ default:
+ column[attrName] = parse(attr.value)(scope);
+ break;
+ }
+ });
- $scope.$watch('body.options.paging.offset', function (newVal) {
- if (_this3.options.paging.size) {
- _this3.onPage({
- offset: newVal,
- size: _this3.options.paging.size
- });
+ var header = c.getElementsByTagName('column-header');
+ if (header.length) {
+ column.headerTemplate = header[0].innerHTML;
+ c.removeChild(header[0]);
}
- });
- }
- }
- _createClass(BodyController, [{
- key: "rowsUpdated",
- value: function rowsUpdated(newVal, oldVal) {
- if (newVal) {
- if (!this.options.paging.externalPaging) {
- this.options.paging.count = newVal.length;
+ if (c.innerHTML !== '') {
+ column.template = c.innerHTML;
}
- this.count = this.options.paging.count;
+ if (visible) _this3.columns[id].push(column);
+ });
+ });
- if (this.treeColumn || this.groupColumn) {
- this.buildRowsByGroup();
- }
+ this.dTables = {};
+ }
+ };
- if (this.options.scrollbarV) {
- var refresh = newVal && oldVal && (newVal.length === oldVal.length || newVal.length < oldVal.length);
+ function DataTableDirective($window, $timeout, $parse) {
+ return {
+ restrict: 'E',
+ replace: true,
+ controller: DataTableController,
+ scope: true,
+ bindToController: {
+ options: '=',
+ rows: '=',
+ selected: '=?',
+ expanded: '=?',
+ onSelect: '&',
+ onSort: '&',
+ onTreeToggle: '&',
+ onPage: '&',
+ onRowClick: '&',
+ onRowDblClick: '&',
+ onColumnResize: '&'
+ },
+ controllerAs: 'dt',
+ template: function template(element) {
+ var columns = element[0].getElementsByTagName('column'),
+ id = ObjectId();
+ DataTableService.saveColumns(id, columns);
- this.getRows(refresh);
- } else {
- var rows = this.rows;
+ return "\n \n \n \n \n \n \n
";
+ },
+ compile: function compile(tElem, tAttrs) {
+ return {
+ pre: function pre($scope, $elm, $attrs, ctrl) {
+ DataTableService.buildColumns($scope, $parse);
- if (this.treeColumn) {
- rows = this.buildTree();
- } else if (this.groupColumn) {
- rows = this.buildGroups();
+ var id = $elm.attr('data-column-id'),
+ columns = DataTableService.columns[id];
+ if (columns) {
+ ctrl.options.columns = columns;
}
- if (this.options.paging.externalPaging) {
- var idxs = this.getFirstLastIndexes(),
- idx = idxs.first;
+ ctrl.transposeColumnDefaults();
+ ctrl.options.internal.scrollBarWidth = ScrollbarWidth();
- this.tempRows.splice(0, this.tempRows.length);
- while (idx < idxs.last) {
- this.tempRows.push(rows[idx++]);
+ function resize() {
+ var rect = $elm[0].getBoundingClientRect();
+
+ ctrl.options.internal.innerWidth = Math.floor(rect.width);
+
+ if (ctrl.options.scrollbarV) {
+ var height = rect.height;
+
+ if (ctrl.options.headerHeight) {
+ height = height - ctrl.options.headerHeight;
+ }
+
+ if (ctrl.options.footerHeight) {
+ height = height - ctrl.options.footerHeight;
+ }
+
+ ctrl.options.internal.bodyHeight = height;
+ ctrl.calculatePageSize();
}
- } else {
- var _tempRows;
- this.tempRows.splice(0, this.tempRows.length);
- (_tempRows = this.tempRows).push.apply(_tempRows, _toConsumableArray(rows));
+ ctrl.adjustColumns();
}
+
+ $window.addEventListener('resize', throttle(function () {
+ $timeout(resize);
+ }));
+
+ var checkVisibility = function checkVisibility() {
+ var bounds = $elm[0].getBoundingClientRect(),
+ visible = bounds.width && bounds.height;
+ if (visible) resize();else $timeout(checkVisibility, 100);
+ };
+ checkVisibility();
+
+ $elm.addClass('dt-loaded');
+
+ $scope.$on('$destroy', function () {
+ _angular2.default.element($window).off('resize');
+ });
}
- }
+ };
}
- }, {
- key: "getFirstLastIndexes",
- value: function getFirstLastIndexes() {
- var firstRowIndex, endIndex;
+ };
+ }
- if (this.options.scrollbarV) {
- firstRowIndex = Math.max(Math.floor((this.options.internal.offsetY || 0) / this.options.rowHeight, 0), 0);
- endIndex = Math.min(firstRowIndex + this.options.paging.size, this.count);
- } else {
- if (this.options.paging.externalPaging) {
- firstRowIndex = Math.max(this.options.paging.offset * this.options.paging.size, 0);
- endIndex = Math.min(firstRowIndex + this.options.paging.size, this.count);
- } else {
- endIndex = this.count;
- }
- }
+ var cache = {};
+ var testStyle = document.createElement('div').style;
- return {
- first: firstRowIndex,
- last: endIndex
- };
+ var prefix = function () {
+ var styles = window.getComputedStyle(document.documentElement, ''),
+ pre = (Array.prototype.slice.call(styles).join('').match(/-(moz|webkit|ms)-/) || styles.OLink === '' && ['', 'o'])[1],
+ dom = 'WebKit|Moz|MS|O'.match(new RegExp('(' + pre + ')', 'i'))[1];
+ return {
+ dom: dom,
+ lowercase: pre,
+ css: '-' + pre + '-',
+ js: pre[0].toUpperCase() + pre.substr(1)
+ };
+ }();
+
+ function GetVendorPrefixedName(property) {
+ var name = CamelCase(property);
+ if (!cache[name]) {
+ if (testStyle[prefix.css + property] !== undefined) {
+ cache[name] = prefix.css + property;
+ } else if (testStyle[property] !== undefined) {
+ cache[name] = property;
}
- }, {
- key: "updatePage",
- value: function updatePage() {
- var curPage = this.options.paging.offset,
- idxs = this.getFirstLastIndexes();
+ }
+ return cache[name];
+ }
- if (this.options.internal.oldScrollPosition === undefined) {
- this.options.internal.oldScrollPosition = 0;
- }
+ var transform = GetVendorPrefixedName('transform');
+ var backfaceVisibility = GetVendorPrefixedName('backfaceVisibility');
+ var hasCSSTransforms = !!GetVendorPrefixedName('transform');
+ var hasCSS3DTransforms = !!GetVendorPrefixedName('perspective');
+ var ua = window.navigator.userAgent;
+ var isSafari = /Safari\//.test(ua) && !/Chrome\//.test(ua);
- var oldScrollPosition = this.options.internal.oldScrollPosition,
- newPage = idxs.first / this.options.paging.size;
+ function TranslateXY(styles, x, y) {
+ if (hasCSSTransforms) {
+ if (!isSafari && hasCSS3DTransforms) {
+ styles[transform] = "translate3d(" + x + "px, " + y + "px, 0)";
+ styles[backfaceVisibility] = 'hidden';
+ } else {
+ styles[CamelCase(transform)] = "translate(" + x + "px, " + y + "px)";
+ }
+ } else {
+ styles.top = y + 'px';
+ styles.left = x + 'px';
+ }
+ }
- this.options.internal.oldScrollPosition = newPage;
+ var HeaderController = function () {
+ function HeaderController() {
+ _classCallCheck(this, HeaderController);
+ }
- if (newPage < oldScrollPosition) {
- newPage = Math.floor(newPage);
- } else if (newPage > oldScrollPosition) {
- newPage = Math.ceil(newPage);
- } else {
- newPage = curPage;
- }
+ _createClass(HeaderController, [{
+ key: "styles",
+ value: function styles() {
+ return {
+ width: this.options.internal.innerWidth + 'px',
+ height: this.options.headerHeight + 'px'
+ };
+ }
+ }, {
+ key: "innerStyles",
+ value: function innerStyles() {
+ return {
+ width: this.columnWidths.total + 'px'
+ };
+ }
+ }, {
+ key: "onSorted",
+ value: function onSorted(sortedColumn) {
+ if (this.options.sortType === 'single') {
+ var unsortColumn = function unsortColumn(column) {
+ if (column !== sortedColumn) {
+ column.sort = undefined;
+ }
+ };
- if (!isNaN(newPage)) {
- this.options.paging.offset = newPage;
+ this.columns.left.forEach(unsortColumn);
+ this.columns.center.forEach(unsortColumn);
+ this.columns.right.forEach(unsortColumn);
}
+
+ this.onSort({
+ column: sortedColumn
+ });
}
}, {
- key: "calculateDepth",
- value: function calculateDepth(row) {
- var depth = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
+ key: "stylesByGroup",
+ value: function stylesByGroup(group) {
+ var styles = {
+ width: this.columnWidths[group] + 'px'
+ };
- var parentProp = this.treeColumn ? this.treeColumn.relationProp : this.groupColumn.prop;
- var prop = this.treeColumn.prop;
- if (!row[parentProp]) {
- return depth;
- }
- if (row.$$depth) {
- return row.$$depth + depth;
+ if (group === 'center') {
+ TranslateXY(styles, this.options.internal.offsetX * -1, 0);
+ } else if (group === 'right') {
+ var offset = (this.columnWidths.total - this.options.internal.innerWidth) * -1;
+ TranslateXY(styles, offset, 0);
}
- var cachedParent = this.index[row[parentProp]];
- if (cachedParent) {
- depth += 1;
- return this.calculateDepth(cachedParent, depth);
- }
- for (var i = 0, len = this.rows.length; i < len; i++) {
- var parent = this.rows[i];
- if (parent[prop] == row[parentProp]) {
- depth += 1;
- return this.calculateDepth(parent, depth);
- }
- }
- return depth;
+ return styles;
}
}, {
- key: "buildRowsByGroup",
- value: function buildRowsByGroup() {
- this.index = {};
- this.rowsByGroup = {};
+ key: "onCheckboxChanged",
+ value: function onCheckboxChanged() {
+ this.onCheckboxChange();
+ }
+ }, {
+ key: "onResized",
+ value: function onResized(column, width) {
+ this.onResize({
+ column: column,
+ width: width
+ });
+ }
+ }]);
- var parentProp = this.treeColumn ? this.treeColumn.relationProp : this.groupColumn.prop;
+ return HeaderController;
+ }();
- for (var i = 0, len = this.rows.length; i < len; i++) {
- var row = this.rows[i];
+ function HeaderDirective($timeout) {
+ return {
+ restrict: 'E',
+ controller: HeaderController,
+ controllerAs: 'header',
+ scope: true,
+ bindToController: {
+ options: '=',
+ columns: '=',
+ columnWidths: '=',
+ onSort: '&',
+ onResize: '&',
+ onCheckboxChange: '&'
+ },
+ template: "\n ",
+ replace: true,
+ link: function link($scope, $elm, $attrs, ctrl) {
- var relVal = row[parentProp];
- if (relVal) {
- if (this.rowsByGroup[relVal]) {
- this.rowsByGroup[relVal].push(row);
- } else {
- this.rowsByGroup[relVal] = [row];
+ $scope.columnsResorted = function (event, columnId) {
+ var col = findColumnById(columnId),
+ parent = _angular2.default.element(event.currentTarget),
+ newIdx = -1;
+
+ _angular2.default.forEach(parent.children(), function (c, i) {
+ if (columnId === _angular2.default.element(c).attr('data-id')) {
+ newIdx = i;
}
- }
+ });
- if (this.treeColumn) {
- var prop = this.treeColumn.prop;
- this.index[row[prop]] = row;
+ $timeout(function () {
+ _angular2.default.forEach(ctrl.columns, function (group) {
+ var idx = group.indexOf(col);
+ if (idx > -1) {
+ var curColAtIdx = group[newIdx],
+ siblingIdx = ctrl.options.columns.indexOf(curColAtIdx),
+ curIdx = ctrl.options.columns.indexOf(col);
- if (row[parentProp] === undefined) {
- row.$$depth = 0;
- } else {
- var parent = this.index[row[parentProp]];
- if (parent === undefined) {
- for (var j = 0; j < len; j++) {
- if (this.rows[j][prop] == relVal) {
- parent = this.rows[j];
- break;
- }
- }
- }
- if (parent.$$depth === undefined) {
- parent.$$depth = this.calculateDepth(parent);
- }
- row.$$depth = parent.$$depth + 1;
- if (parent.$$children) {
- parent.$$children.push(row[prop]);
- } else {
- parent.$$children = [row[prop]];
- }
- }
- }
- }
- }
- }, {
- key: "buildGroups",
- value: function buildGroups() {
- var _this4 = this;
+ ctrl.options.columns.splice(curIdx, 1);
+ ctrl.options.columns.splice(siblingIdx, 0, col);
- var temp = [];
+ return false;
+ }
+ });
+ });
+ };
- angular.forEach(this.rowsByGroup, function (v, k) {
- temp.push({
- name: k,
- group: true
+ var findColumnById = function findColumnById(columnId) {
+ var columns = ctrl.columns.left.concat(ctrl.columns.center).concat(ctrl.columns.right);
+ return columns.find(function (c) {
+ return c.$id === columnId;
});
+ };
+ }
+ };
+ }
- if (_this4.expanded[k]) {
- temp.push.apply(temp, _toConsumableArray(v));
- }
- });
+ var HeaderCellController = function () {
+ function HeaderCellController() {
+ _classCallCheck(this, HeaderCellController);
+ }
- return temp;
+ _createClass(HeaderCellController, [{
+ key: "styles",
+ value: function styles() {
+ return {
+ width: this.column.width + 'px',
+ minWidth: this.column.minWidth + 'px',
+ maxWidth: this.column.maxWidth + 'px',
+ height: this.column.height + 'px'
+ };
}
}, {
- key: "isSelected",
- value: function isSelected(row) {
- var selected = false;
+ key: "cellClass",
+ value: function cellClass() {
+ var cls = {
+ 'sortable': this.column.sortable,
+ 'resizable': this.column.resizable
+ };
- if (this.options.selectable) {
- if (this.options.multiSelect) {
- selected = this.selected.indexOf(row) > -1;
- } else {
- selected = this.selected === row;
- }
+ if (this.column.headerClassName) {
+ cls[this.column.headerClassName] = true;
}
- return selected;
+ return cls;
}
}, {
- key: "buildTree",
- value: function buildTree() {
- var temp = [],
- self = this;
+ key: "onSorted",
+ value: function onSorted() {
+ if (this.column.sortable) {
+ this.column.sort = NextSortDirection(this.sortType, this.column.sort);
- function addChildren(fromArray, toArray, level) {
- fromArray.forEach(function (row) {
- var relVal = row[self.treeColumn.relationProp],
- key = row[self.treeColumn.prop],
- groupRows = self.rowsByGroup[key],
- expanded = self.expanded[key];
+ if (this.column.sort === undefined) {
+ this.column.sortPriority = undefined;
+ }
- if (level > 0 || !relVal) {
- toArray.push(row);
- if (groupRows && groupRows.length > 0 && expanded) {
- addChildren(groupRows, toArray, level + 1);
- }
- }
+ this.onSort({
+ column: this.column
});
}
-
- addChildren(this.rows, temp, 0);
-
- return temp;
}
}, {
- key: "getRows",
- value: function getRows(refresh) {
- if ((this.treeColumn || this.groupColumn) && !this.rowsByGroup) {
- return false;
- }
+ key: "sortClass",
+ value: function sortClass() {
+ return {
+ 'sort-btn': true,
+ 'sort-asc icon-down': this.column.sort === 'asc',
+ 'sort-desc icon-up': this.column.sort === 'desc'
+ };
+ }
+ }, {
+ key: "onResized",
+ value: function onResized(width, column) {
+ this.onResize({
+ column: column,
+ width: width
+ });
+ }
+ }, {
+ key: "onCheckboxChange",
+ value: function onCheckboxChange() {
+ this.onCheckboxChanged();
+ }
+ }]);
- var temp;
+ return HeaderCellController;
+ }();
- if (this.treeColumn) {
- temp = this.treeTemp || [];
+ function HeaderCellDirective($compile) {
+ return {
+ restrict: 'E',
+ controller: HeaderCellController,
+ controllerAs: 'hcell',
+ scope: true,
+ bindToController: {
+ options: '=',
+ column: '=',
+ onCheckboxChange: '&',
+ onSort: '&',
+ sortType: '=',
+ onResize: '&',
+ selected: '='
+ },
+ replace: true,
+ template: "",
+ compile: function compile() {
+ return {
+ pre: function pre($scope, $elm, $attrs, ctrl) {
+ var label = $elm[0].querySelector('.dt-header-cell-label'),
+ cellScope = void 0;
- if (refresh || !this.treeTemp) {
- this.treeTemp = temp = this.buildTree();
- this.count = temp.length;
+ if (ctrl.column.headerTemplate || ctrl.column.headerRenderer) {
+ cellScope = ctrl.options.$outer.$new(false);
- this.tempRows.splice(0, this.tempRows.length);
- }
- } else if (this.groupColumn) {
- temp = this.groupsTemp || [];
+ cellScope.$header = ctrl.column.name;
+ cellScope.$index = $scope.$index;
+ }
- if (refresh || !this.groupsTemp) {
- this.groupsTemp = temp = this.buildGroups();
- this.count = temp.length;
- }
- } else {
- temp = this.rows;
- if (refresh === true) {
- this.tempRows.splice(0, this.tempRows.length);
+ if (ctrl.column.headerTemplate) {
+ var elm = _angular2.default.element("" + ctrl.column.headerTemplate.trim() + " ");
+ _angular2.default.element(label).append($compile(elm)(cellScope));
+ } else if (ctrl.column.headerRenderer) {
+ var _elm = _angular2.default.element(ctrl.column.headerRenderer($elm));
+ _angular2.default.element(label).append($compile(_elm)(cellScope)[0]);
+ } else {
+ var val = ctrl.column.name;
+ if (val === undefined || val === null) val = '';
+ label.textContent = val;
+ }
}
- }
-
- var idx = 0,
- indexes = this.getFirstLastIndexes(),
- rowIndex = indexes.first;
+ };
+ }
+ };
+ }
- this.tempRows.splice(0, indexes.last - indexes.first);
+ var BodyController = function () {
+ function BodyController($scope, $timeout) {
+ var _this4 = this;
- while (rowIndex < indexes.last && rowIndex < this.count) {
- var row = temp[rowIndex];
- if (row) {
- row.$$index = rowIndex;
- this.tempRows[idx] = row;
- }
- idx++;
- rowIndex++;
- }
+ _classCallCheck(this, BodyController);
- this.options.internal.styleTranslator.update(this.tempRows);
+ this.$scope = $scope;
+ this.tempRows = [];
- return this.tempRows;
- }
- }, {
- key: "styles",
- value: function styles() {
- var styles = {
- width: this.options.internal.innerWidth + 'px'
- };
+ this.treeColumn = this.options.columns.find(function (c) {
+ return c.isTreeColumn;
+ });
- if (!this.options.scrollbarV) {
- styles.overflowY = 'hidden';
- } else if (this.options.scrollbarH === false) {
- styles.overflowX = 'hidden';
- }
+ this.groupColumn = this.options.columns.find(function (c) {
+ return c.group;
+ });
- if (this.options.scrollbarV) {
- styles.height = this.options.internal.bodyHeight + 'px';
- }
+ $scope.$watchCollection('body.rows', this.rowsUpdated.bind(this));
- return styles;
- }
- }, {
- key: "rowStyles",
- value: function rowStyles(row) {
- var styles = {};
+ if (this.options.scrollbarV || !this.options.scrollbarV && this.options.paging.externalPaging) {
+ var sized = false;
+ $scope.$watch('body.options.paging.size', function (newVal, oldVal) {
+ if (!sized || newVal > oldVal) {
+ _this4.getRows();
+ sized = true;
+ }
+ });
- if (this.options.rowHeight === 'auto') {
- styles.height = this.options.rowHeight + 'px';
- }
+ $scope.$watch('body.options.paging.count', function (count) {
+ _this4.count = count;
+ _this4.updatePage();
+ });
- return styles;
- }
- }, {
- key: "groupRowStyles",
- value: function groupRowStyles(row) {
- var styles = this.rowStyles(row);
- styles.width = this.columnWidths.total + 'px';
- return styles;
+ $scope.$watch('body.options.paging.offset', function (newVal) {
+ if (_this4.options.paging.size) {
+ _this4.onPage({
+ offset: newVal,
+ size: _this4.options.paging.size
+ });
+ }
+ });
}
- }, {
- key: "rowClasses",
- value: function rowClasses(row) {
- var styles = {
- 'selected': this.isSelected(row),
- 'dt-row-even': row && row.$$index % 2 === 0,
- 'dt-row-odd': row && row.$$index % 2 !== 0
- };
+ }
- if (this.treeColumn) {
- styles['dt-leaf'] = this.rowsByGroup[row[this.treeColumn.relationProp]];
+ _createClass(BodyController, [{
+ key: "rowsUpdated",
+ value: function rowsUpdated(newVal, oldVal) {
+ if (newVal) {
+ if (!this.options.paging.externalPaging) {
+ this.options.paging.count = newVal.length;
+ }
- styles['dt-has-leafs'] = this.rowsByGroup[row[this.treeColumn.prop]];
+ this.count = this.options.paging.count;
- styles['dt-depth-' + row.$$depth] = true;
- }
+ if (this.treeColumn || this.groupColumn) {
+ this.buildRowsByGroup();
+ }
- return styles;
- }
- }, {
- key: "getRowValue",
- value: function getRowValue(idx) {
- return this.tempRows[idx];
- }
- }, {
- key: "getRowExpanded",
- value: function getRowExpanded(row) {
- if (this.treeColumn) {
- return this.expanded[row[this.treeColumn.prop]];
- } else if (this.groupColumn) {
- return this.expanded[row.name];
- }
- }
- }, {
- key: "getRowHasChildren",
- value: function getRowHasChildren(row) {
- if (!this.treeColumn) return;
- var children = this.rowsByGroup[row[this.treeColumn.prop]];
- return children !== undefined || children && !children.length;
- }
- }, {
- key: "onTreeToggled",
- value: function onTreeToggled(row, cell) {
- var val = row[this.treeColumn.prop];
- this.expanded[val] = !this.expanded[val];
+ if (this.options.scrollbarV) {
+ var refresh = newVal && oldVal && (newVal.length === oldVal.length || newVal.length < oldVal.length);
- if (this.options.scrollbarV) {
- this.getRows(true);
- } else {
- var _tempRows2;
+ this.getRows(refresh);
+ } else {
+ var rows = this.rows;
- var values = this.buildTree();
- this.tempRows.splice(0, this.tempRows.length);
- (_tempRows2 = this.tempRows).push.apply(_tempRows2, _toConsumableArray(values));
- }
+ if (this.treeColumn) {
+ rows = this.buildTree();
+ } else if (this.groupColumn) {
+ rows = this.buildGroups();
+ }
- this.onTreeToggle({
- row: row,
- cell: cell
- });
+ if (this.options.paging.externalPaging) {
+ var idxs = this.getFirstLastIndexes(),
+ idx = idxs.first;
+
+ this.tempRows.splice(0, this.tempRows.length);
+ while (idx < idxs.last) {
+ this.tempRows.push(rows[idx++]);
+ }
+ } else {
+ var _tempRows;
+
+ this.tempRows.splice(0, this.tempRows.length);
+ (_tempRows = this.tempRows).push.apply(_tempRows, _toConsumableArray(rows));
+ }
+ }
+ }
}
}, {
- key: "onGroupToggle",
- value: function onGroupToggle(row) {
- this.expanded[row.name] = !this.expanded[row.name];
+ key: "getFirstLastIndexes",
+ value: function getFirstLastIndexes() {
+ var firstRowIndex, endIndex;
if (this.options.scrollbarV) {
- this.getRows(true);
+ firstRowIndex = Math.max(Math.floor((this.options.internal.offsetY || 0) / this.options.rowHeight, 0), 0);
+ endIndex = Math.min(firstRowIndex + this.options.paging.size, this.count);
} else {
- var _tempRows3;
-
- var values = this.buildGroups();
- this.tempRows.splice(0, this.tempRows.length);
- (_tempRows3 = this.tempRows).push.apply(_tempRows3, _toConsumableArray(values));
+ if (this.options.paging.externalPaging) {
+ firstRowIndex = Math.max(this.options.paging.offset * this.options.paging.size, 0);
+ endIndex = Math.min(firstRowIndex + this.options.paging.size, this.count);
+ } else {
+ endIndex = this.count;
+ }
}
- }
- }]);
-
- return BodyController;
- }();
-
- function BodyDirective($timeout) {
- return {
- restrict: 'E',
- controller: BodyController,
- controllerAs: 'body',
- bindToController: {
- columns: '=',
- columnWidths: '=',
- rows: '=',
- options: '=',
- selected: '=?',
- expanded: '=?',
- onPage: '&',
- onTreeToggle: '&',
- onSelect: '&',
- onRowClick: '&',
- onRowDblClick: '&'
- },
- scope: true,
- template: "\n \n \n
\n \n \n \n \n \n
\n
\n
\n
\n
"
- };
- }
-
- function NextSortDirection(sortType, currentSort) {
- if (sortType === 'single') {
- if (currentSort === 'asc') {
- return 'desc';
- } else {
- return 'asc';
- }
- } else {
- if (!currentSort) {
- return 'asc';
- } else if (currentSort === 'asc') {
- return 'desc';
- } else if (currentSort === 'desc') {
- return undefined;
- }
- }
- }
-
- var HeaderCellController = function () {
- function HeaderCellController() {
- _classCallCheck(this, HeaderCellController);
- }
- _createClass(HeaderCellController, [{
- key: "styles",
- value: function styles() {
return {
- width: this.column.width + 'px',
- minWidth: this.column.minWidth + 'px',
- maxWidth: this.column.maxWidth + 'px',
- height: this.column.height + 'px'
+ first: firstRowIndex,
+ last: endIndex
};
}
}, {
- key: "cellClass",
- value: function cellClass() {
- var cls = {
- 'sortable': this.column.sortable,
- 'resizable': this.column.resizable
- };
+ key: "updatePage",
+ value: function updatePage() {
+ var curPage = this.options.paging.offset,
+ idxs = this.getFirstLastIndexes();
- if (this.column.headerClassName) {
- cls[this.column.headerClassName] = true;
+ if (this.options.internal.oldScrollPosition === undefined) {
+ this.options.internal.oldScrollPosition = 0;
}
- return cls;
- }
- }, {
- key: "onSorted",
- value: function onSorted() {
- if (this.column.sortable) {
- this.column.sort = NextSortDirection(this.sortType, this.column.sort);
+ var oldScrollPosition = this.options.internal.oldScrollPosition,
+ newPage = idxs.first / this.options.paging.size;
- if (this.column.sort === undefined) {
- this.column.sortPriority = undefined;
- }
+ this.options.internal.oldScrollPosition = newPage;
- this.onSort({
- column: this.column
- });
+ if (newPage < oldScrollPosition) {
+ newPage = Math.floor(newPage);
+ } else if (newPage > oldScrollPosition) {
+ newPage = Math.ceil(newPage);
+ } else {
+ newPage = curPage;
+ }
+
+ if (!isNaN(newPage)) {
+ this.options.paging.offset = newPage;
}
}
}, {
- key: "sortClass",
- value: function sortClass() {
- return {
- 'sort-btn': true,
- 'sort-asc icon-down': this.column.sort === 'asc',
- 'sort-desc icon-up': this.column.sort === 'desc'
- };
- }
- }, {
- key: "onResized",
- value: function onResized(width, column) {
- this.onResize({
- column: column,
- width: width
- });
- }
- }, {
- key: "onCheckboxChange",
- value: function onCheckboxChange() {
- this.onCheckboxChanged();
- }
- }]);
+ key: "calculateDepth",
+ value: function calculateDepth(row) {
+ var depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
- return HeaderCellController;
- }();
+ var parentProp = this.treeColumn ? this.treeColumn.relationProp : this.groupColumn.prop;
+ var prop = this.treeColumn.prop;
+ if (!row[parentProp]) {
+ return depth;
+ }
+ if (row.$$depth) {
+ return row.$$depth + depth;
+ }
- function HeaderCellDirective($compile) {
- return {
- restrict: 'E',
- controller: HeaderCellController,
- controllerAs: 'hcell',
- scope: true,
- bindToController: {
- options: '=',
- column: '=',
- onCheckboxChange: '&',
- onSort: '&',
- sortType: '=',
- onResize: '&',
- selected: '='
- },
- replace: true,
- template: "",
- compile: function compile() {
- return {
- pre: function pre($scope, $elm, $attrs, ctrl) {
- var label = $elm[0].querySelector('.dt-header-cell-label'),
- cellScope = void 0;
+ var cachedParent = this.index[row[parentProp]];
+ if (cachedParent) {
+ depth += 1;
+ return this.calculateDepth(cachedParent, depth);
+ }
+ for (var i = 0, len = this.rows.length; i < len; i++) {
+ var parent = this.rows[i];
+ if (parent[prop] == row[parentProp]) {
+ depth += 1;
+ return this.calculateDepth(parent, depth);
+ }
+ }
+ return depth;
+ }
+ }, {
+ key: "buildRowsByGroup",
+ value: function buildRowsByGroup() {
+ this.index = {};
+ this.rowsByGroup = {};
- if (ctrl.column.headerTemplate || ctrl.column.headerRenderer) {
- cellScope = ctrl.options.$outer.$new(false);
+ var parentProp = this.treeColumn ? this.treeColumn.relationProp : this.groupColumn.prop;
- cellScope.$header = ctrl.column.name;
- cellScope.$index = $scope.$index;
- }
+ for (var i = 0, len = this.rows.length; i < len; i++) {
+ var row = this.rows[i];
- if (ctrl.column.headerTemplate) {
- var elm = angular.element("" + ctrl.column.headerTemplate.trim() + " ");
- angular.element(label).append($compile(elm)(cellScope));
- } else if (ctrl.column.headerRenderer) {
- var _elm = angular.element(ctrl.column.headerRenderer($elm));
- angular.element(label).append($compile(_elm)(cellScope)[0]);
+ var relVal = row[parentProp];
+ if (relVal) {
+ if (this.rowsByGroup[relVal]) {
+ this.rowsByGroup[relVal].push(row);
} else {
- var val = ctrl.column.name;
- if (val === undefined || val === null) val = '';
- label.textContent = val;
+ this.rowsByGroup[relVal] = [row];
}
}
- };
- }
- };
- }
- var HeaderController = function () {
- function HeaderController() {
- _classCallCheck(this, HeaderController);
- }
+ if (this.treeColumn) {
+ var prop = this.treeColumn.prop;
+ this.index[row[prop]] = row;
- _createClass(HeaderController, [{
- key: "styles",
- value: function styles() {
- return {
- width: this.options.internal.innerWidth + 'px',
- height: this.options.headerHeight + 'px'
- };
- }
- }, {
- key: "innerStyles",
- value: function innerStyles() {
- return {
- width: this.columnWidths.total + 'px'
- };
+ if (row[parentProp] === undefined) {
+ row.$$depth = 0;
+ } else {
+ var parent = this.index[row[parentProp]];
+ if (parent === undefined) {
+ for (var j = 0; j < len; j++) {
+ if (this.rows[j][prop] == relVal) {
+ parent = this.rows[j];
+ break;
+ }
+ }
+ }
+ if (parent.$$depth === undefined) {
+ parent.$$depth = this.calculateDepth(parent);
+ }
+ row.$$depth = parent.$$depth + 1;
+ if (parent.$$children) {
+ parent.$$children.push(row[prop]);
+ } else {
+ parent.$$children = [row[prop]];
+ }
+ }
+ }
+ }
}
}, {
- key: "onSorted",
- value: function onSorted(sortedColumn) {
- if (this.options.sortType === 'single') {
- var unsortColumn = function unsortColumn(column) {
- if (column !== sortedColumn) {
- column.sort = undefined;
- }
- };
+ key: "buildGroups",
+ value: function buildGroups() {
+ var _this5 = this;
- this.columns.left.forEach(unsortColumn);
- this.columns.center.forEach(unsortColumn);
- this.columns.right.forEach(unsortColumn);
- }
+ var temp = [];
- this.onSort({
- column: sortedColumn
+ _angular2.default.forEach(this.rowsByGroup, function (v, k) {
+ temp.push({
+ name: k,
+ group: true
+ });
+
+ if (_this5.expanded[k]) {
+ temp.push.apply(temp, _toConsumableArray(v));
+ }
});
+
+ return temp;
}
}, {
- key: "stylesByGroup",
- value: function stylesByGroup(group) {
- var styles = {
- width: this.columnWidths[group] + 'px'
- };
+ key: "isSelected",
+ value: function isSelected(row) {
+ var selected = false;
- if (group === 'center') {
- TranslateXY(styles, this.options.internal.offsetX * -1, 0);
- } else if (group === 'right') {
- var offset = (this.columnWidths.total - this.options.internal.innerWidth) * -1;
- TranslateXY(styles, offset, 0);
+ if (this.options.selectable) {
+ if (this.options.multiSelect) {
+ selected = this.selected.indexOf(row) > -1;
+ } else {
+ selected = this.selected === row;
+ }
}
- return styles;
- }
- }, {
- key: "onCheckboxChanged",
- value: function onCheckboxChanged() {
- this.onCheckboxChange();
+ return selected;
}
}, {
- key: "onResized",
- value: function onResized(column, width) {
- this.onResize({
- column: column,
- width: width
- });
- }
- }]);
-
- return HeaderController;
- }();
-
- function HeaderDirective($timeout) {
- return {
- restrict: 'E',
- controller: HeaderController,
- controllerAs: 'header',
- scope: true,
- bindToController: {
- options: '=',
- columns: '=',
- columnWidths: '=',
- onSort: '&',
- onResize: '&',
- onCheckboxChange: '&'
- },
- template: "\n ",
- replace: true,
- link: function link($scope, $elm, $attrs, ctrl) {
+ key: "buildTree",
+ value: function buildTree() {
+ var temp = [],
+ self = this;
- $scope.columnsResorted = function (event, columnId) {
- var col = findColumnById(columnId),
- parent = angular.element(event.currentTarget),
- newIdx = -1;
+ function addChildren(fromArray, toArray, level) {
+ fromArray.forEach(function (row) {
+ var relVal = row[self.treeColumn.relationProp],
+ key = row[self.treeColumn.prop],
+ groupRows = self.rowsByGroup[key],
+ expanded = self.expanded[key];
- angular.forEach(parent.children(), function (c, i) {
- if (columnId === angular.element(c).attr('data-id')) {
- newIdx = i;
+ if (level > 0 || !relVal) {
+ toArray.push(row);
+ if (groupRows && groupRows.length > 0 && expanded) {
+ addChildren(groupRows, toArray, level + 1);
+ }
}
});
+ }
- $timeout(function () {
- angular.forEach(ctrl.columns, function (group) {
- var idx = group.indexOf(col);
- if (idx > -1) {
- var curColAtIdx = group[newIdx],
- siblingIdx = ctrl.options.columns.indexOf(curColAtIdx),
- curIdx = ctrl.options.columns.indexOf(col);
-
- ctrl.options.columns.splice(curIdx, 1);
- ctrl.options.columns.splice(siblingIdx, 0, col);
-
- return false;
- }
- });
- });
- };
+ addChildren(this.rows, temp, 0);
- var findColumnById = function findColumnById(columnId) {
- var columns = ctrl.columns.left.concat(ctrl.columns.center).concat(ctrl.columns.right);
- return columns.find(function (c) {
- return c.$id === columnId;
- });
- };
+ return temp;
}
- };
- }
-
- function SortableDirective($timeout) {
- return {
- restrict: 'A',
- scope: {
- isSortable: '=sortable',
- onSortableSort: '&'
- },
- link: function link($scope, $element, $attrs) {
- var rootEl = $element[0],
- dragEl,
- nextEl,
- dropEl;
-
- function isbefore(a, b) {
- if (a.parentNode == b.parentNode) {
- for (var cur = a; cur; cur = cur.previousSibling) {
- if (cur === b) {
- return true;
- }
- }
- }
+ }, {
+ key: "getRows",
+ value: function getRows(refresh) {
+ if ((this.treeColumn || this.groupColumn) && !this.rowsByGroup) {
return false;
- };
-
- function onDragEnter(e) {
- var target = e.target;
- if (isbefore(dragEl, target)) {
- target.parentNode.insertBefore(dragEl, target);
- } else if (target.nextSibling && target.hasAttribute('draggable')) {
- target.parentNode.insertBefore(dragEl, target.nextSibling.nextSibling);
- }
- };
+ }
- function onDragEnd(evt) {
- evt.preventDefault();
+ var temp;
- dragEl.classList.remove('dt-clone');
+ if (this.treeColumn) {
+ temp = this.treeTemp || [];
- $element.off('dragend', onDragEnd);
- $element.off('dragenter', onDragEnter);
+ if (refresh || !this.treeTemp) {
+ this.treeTemp = temp = this.buildTree();
+ this.count = temp.length;
- if (nextEl !== dragEl.nextSibling) {
- $scope.onSortableSort({
- event: evt,
- columnId: angular.element(dragEl).attr('data-id')
- });
+ this.tempRows.splice(0, this.tempRows.length);
}
- };
+ } else if (this.groupColumn) {
+ temp = this.groupsTemp || [];
- function onDragStart(evt) {
- if (!$scope.isSortable) return false;
- evt = evt.originalEvent || evt;
+ if (refresh || !this.groupsTemp) {
+ this.groupsTemp = temp = this.buildGroups();
+ this.count = temp.length;
+ }
+ } else {
+ temp = this.rows;
+ if (refresh === true) {
+ this.tempRows.splice(0, this.tempRows.length);
+ }
+ }
- dragEl = evt.target;
- nextEl = dragEl.nextSibling;
- dragEl.classList.add('dt-clone');
+ var idx = 0,
+ indexes = this.getFirstLastIndexes(),
+ rowIndex = indexes.first;
- evt.dataTransfer.effectAllowed = 'move';
- evt.dataTransfer.setData('Text', dragEl.textContent);
+ this.tempRows.splice(0, indexes.last - indexes.first);
- $element.on('dragenter', onDragEnter);
- $element.on('dragend', onDragEnd);
- };
+ while (rowIndex < indexes.last && rowIndex < this.count) {
+ var row = temp[rowIndex];
+ if (row) {
+ row.$$index = rowIndex;
+ this.tempRows[idx] = row;
+ }
+ idx++;
+ rowIndex++;
+ }
- $element.on('dragstart', onDragStart);
+ this.options.internal.styleTranslator.update(this.tempRows);
- $scope.$on('$destroy', function () {
- $element.off('dragstart', onDragStart);
- });
+ return this.tempRows;
}
- };
- }
+ }, {
+ key: "styles",
+ value: function styles() {
+ var styles = {
+ width: this.options.internal.innerWidth + 'px'
+ };
- function ResizableDirective($document, $timeout) {
- return {
- restrict: 'A',
- scope: {
- isResizable: '=resizable',
- minWidth: '=',
- maxWidth: '=',
- onResize: '&'
- },
- link: function link($scope, $element, $attrs) {
- if ($scope.isResizable) {
- $element.addClass('resizable');
+ if (!this.options.scrollbarV) {
+ styles.overflowY = 'hidden';
+ } else if (this.options.scrollbarH === false) {
+ styles.overflowX = 'hidden';
}
- var handle = angular.element(" "),
- parent = $element.parent(),
- prevScreenX;
+ if (this.options.scrollbarV) {
+ styles.height = this.options.internal.bodyHeight + 'px';
+ }
- handle.on('mousedown', function (event) {
- if (!$element[0].classList.contains('resizable')) {
- return false;
- }
+ return styles;
+ }
+ }, {
+ key: "rowStyles",
+ value: function rowStyles(row) {
+ var styles = {};
- event.stopPropagation();
- event.preventDefault();
+ if (this.options.rowHeight === 'auto') {
+ styles.height = this.options.rowHeight + 'px';
+ }
- $document.on('mousemove', mousemove);
- $document.on('mouseup', mouseup);
- });
+ return styles;
+ }
+ }, {
+ key: "groupRowStyles",
+ value: function groupRowStyles(row) {
+ var styles = this.rowStyles(row);
+ styles.width = this.columnWidths.total + 'px';
+ return styles;
+ }
+ }, {
+ key: "rowClasses",
+ value: function rowClasses(row) {
+ var styles = {
+ 'selected': this.isSelected(row),
+ 'dt-row-even': row && row.$$index % 2 === 0,
+ 'dt-row-odd': row && row.$$index % 2 !== 0
+ };
- function mousemove(event) {
- event = event.originalEvent || event;
+ if (this.treeColumn) {
+ styles['dt-leaf'] = this.rowsByGroup[row[this.treeColumn.relationProp]];
- var width = parent[0].clientWidth,
- movementX = event.movementX || event.mozMovementX || event.screenX - prevScreenX,
- newWidth = width + (movementX || 0);
+ styles['dt-has-leafs'] = this.rowsByGroup[row[this.treeColumn.prop]];
- prevScreenX = event.screenX;
+ styles['dt-depth-' + row.$$depth] = true;
+ }
- if ((!$scope.minWidth || newWidth >= $scope.minWidth) && (!$scope.maxWidth || newWidth <= $scope.maxWidth)) {
- parent.css({
- width: newWidth + 'px'
- });
- }
+ return styles;
+ }
+ }, {
+ key: "getRowValue",
+ value: function getRowValue(idx) {
+ return this.tempRows[idx];
+ }
+ }, {
+ key: "getRowExpanded",
+ value: function getRowExpanded(row) {
+ if (this.treeColumn) {
+ return this.expanded[row[this.treeColumn.prop]];
+ } else if (this.groupColumn) {
+ return this.expanded[row.name];
}
+ }
+ }, {
+ key: "getRowHasChildren",
+ value: function getRowHasChildren(row) {
+ if (!this.treeColumn) return;
+ var children = this.rowsByGroup[row[this.treeColumn.prop]];
+ return children !== undefined || children && !children.length;
+ }
+ }, {
+ key: "onTreeToggled",
+ value: function onTreeToggled(row, cell) {
+ var val = row[this.treeColumn.prop];
+ this.expanded[val] = !this.expanded[val];
- function mouseup() {
- if ($scope.onResize) {
- $timeout(function () {
- var width = parent[0].clientWidth;
- if (width < $scope.minWidth) {
- width = $scope.minWidth;
- }
- $scope.onResize({ width: width });
- });
- }
+ if (this.options.scrollbarV) {
+ this.getRows(true);
+ } else {
+ var _tempRows2;
- $document.unbind('mousemove', mousemove);
- $document.unbind('mouseup', mouseup);
+ var values = this.buildTree();
+ this.tempRows.splice(0, this.tempRows.length);
+ (_tempRows2 = this.tempRows).push.apply(_tempRows2, _toConsumableArray(values));
}
- $element.append(handle);
+ this.onTreeToggle({
+ row: row,
+ cell: cell
+ });
}
- };
- }
-
- function throttle(func, wait, options) {
- var context, args, result;
- var timeout = null;
- var previous = 0;
- options || (options = {});
- var later = function later() {
- previous = options.leading === false ? 0 : new Date();
- timeout = null;
- result = func.apply(context, args);
- };
- return function () {
- var now = new Date();
- if (!previous && options.leading === false) previous = now;
- var remaining = wait - (now - previous);
- context = this;
- args = arguments;
- if (remaining <= 0) {
- clearTimeout(timeout);
- timeout = null;
- previous = now;
- result = func.apply(context, args);
- } else if (!timeout && options.trailing !== false) {
- timeout = setTimeout(later, remaining);
- }
- return result;
- };
- }
-
- function ScrollbarWidth() {
- var outer = document.createElement("div");
- outer.style.visibility = "hidden";
- outer.style.width = "100px";
- outer.style.msOverflowStyle = "scrollbar";
- document.body.appendChild(outer);
+ }, {
+ key: "onGroupToggle",
+ value: function onGroupToggle(row) {
+ this.expanded[row.name] = !this.expanded[row.name];
- var widthNoScroll = outer.offsetWidth;
- outer.style.overflow = "scroll";
+ if (this.options.scrollbarV) {
+ this.getRows(true);
+ } else {
+ var _tempRows3;
- var inner = document.createElement("div");
- inner.style.width = "100%";
- outer.appendChild(inner);
+ var values = this.buildGroups();
+ this.tempRows.splice(0, this.tempRows.length);
+ (_tempRows3 = this.tempRows).push.apply(_tempRows3, _toConsumableArray(values));
+ }
+ }
+ }]);
- var widthWithScroll = inner.offsetWidth;
- outer.parentNode.removeChild(outer);
+ return BodyController;
+ }();
- return widthNoScroll - widthWithScroll;
+ function BodyDirective($timeout) {
+ return {
+ restrict: 'E',
+ controller: BodyController,
+ controllerAs: 'body',
+ bindToController: {
+ columns: '=',
+ columnWidths: '=',
+ rows: '=',
+ options: '=',
+ selected: '=?',
+ expanded: '=?',
+ onPage: '&',
+ onTreeToggle: '&',
+ onSelect: '&',
+ onRowClick: '&',
+ onRowDblClick: '&'
+ },
+ scope: true,
+ template: "\n \n \n
\n \n \n \n \n \n
\n
\n
\n
\n
"
+ };
}
- var DataTableService = {
- columns: {},
- dTables: {},
+ var StyleTranslator = function () {
+ function StyleTranslator(height) {
+ _classCallCheck(this, StyleTranslator);
- saveColumns: function saveColumns(id, columnElms) {
- if (columnElms && columnElms.length) {
- var columnsArray = [].slice.call(columnElms);
- this.dTables[id] = columnsArray;
- }
- },
- buildColumns: function buildColumns(scope, parse) {
- var _this5 = this;
+ this.height = height;
+ this.map = new Map();
+ }
- angular.forEach(this.dTables, function (columnElms, id) {
- _this5.columns[id] = [];
+ _createClass(StyleTranslator, [{
+ key: "update",
+ value: function update(rows) {
+ var n = 0;
+ while (n <= this.map.size) {
+ var dom = this.map.get(n);
+ var model = rows[n];
+ if (dom && model) {
+ TranslateXY(dom[0].style, 0, model.$$index * this.height);
+ }
+ n++;
+ }
+ }
+ }, {
+ key: "register",
+ value: function register(idx, dom) {
+ this.map.set(idx, dom);
+ }
+ }]);
- angular.forEach(columnElms, function (c) {
- var column = {};
+ return StyleTranslator;
+ }();
- var visible = true;
+ function ScrollerDirective($timeout, $rootScope) {
+ return {
+ restrict: 'E',
+ require: '^dtBody',
+ transclude: true,
+ replace: true,
+ template: "
",
+ link: function link($scope, $elm, $attrs, ctrl) {
+ var ticking = false,
+ lastScrollY = 0,
+ lastScrollX = 0,
+ parent = $elm.parent();
- angular.forEach(c.attributes, function (attr) {
- var attrName = CamelCase(attr.name);
+ ctrl.options.internal.styleTranslator = new StyleTranslator(ctrl.options.rowHeight);
- switch (attrName) {
- case 'class':
- column.className = attr.value;
- break;
- case 'name':
- case 'prop':
- column[attrName] = attr.value;
- break;
- case 'headerRenderer':
- case 'cellRenderer':
- case 'cellDataGetter':
- column[attrName] = parse(attr.value);
- break;
- case 'visible':
- visible = parse(attr.value)(scope);
- break;
- default:
- column[attrName] = parse(attr.value)(scope);
- break;
- }
- });
+ ctrl.options.internal.setYOffset = function (offsetY) {
+ parent[0].scrollTop = offsetY;
+ };
- var header = c.getElementsByTagName('column-header');
- if (header.length) {
- column.headerTemplate = header[0].innerHTML;
- c.removeChild(header[0]);
- }
+ function update() {
+ ctrl.options.internal.offsetY = lastScrollY;
+ ctrl.options.internal.offsetX = lastScrollX;
+ ctrl.updatePage();
- if (c.innerHTML !== '') {
- column.template = c.innerHTML;
+ if (ctrl.options.scrollbarV) {
+ ctrl.getRows();
}
- if (visible) _this5.columns[id].push(column);
- });
- });
-
- this.dTables = {};
- }
- };
-
- function ObjectId() {
- var timestamp = (new Date().getTime() / 1000 | 0).toString(16);
- return timestamp + 'xxxxxxxxxxxxxxxx'.replace(/[x]/g, function () {
- return (Math.random() * 16 | 0).toString(16);
- }).toLowerCase();
- }
+ ctrl.options.$outer.$digest();
- function ScaleColumns(colsByGroup, maxWidth, totalFlexGrow) {
- angular.forEach(colsByGroup, function (cols) {
- cols.forEach(function (column) {
- if (!column.canAutoResize) {
- maxWidth -= column.width;
- totalFlexGrow -= column.flexGrow;
- } else {
- column.width = 0;
+ ticking = false;
}
- });
- });
- var hasMinWidth = {};
- var remainingWidth = maxWidth;
-
- var _loop = function _loop() {
- var widthPerFlexPoint = remainingWidth / totalFlexGrow;
- remainingWidth = 0;
- angular.forEach(colsByGroup, function (cols) {
- cols.forEach(function (column, i) {
- if (column.canAutoResize && !hasMinWidth[i]) {
- var newWidth = column.width + column.flexGrow * widthPerFlexPoint;
- if (column.minWidth !== undefined && newWidth < column.minWidth) {
- remainingWidth += newWidth - column.minWidth;
- column.width = column.minWidth;
- hasMinWidth[i] = true;
- } else {
- column.width = newWidth;
- }
+ function requestTick() {
+ if (!ticking) {
+ requestAnimFrame(update);
+ ticking = true;
}
- });
- });
- };
+ }
- do {
- _loop();
- } while (remainingWidth !== 0);
- }
+ parent.on('scroll', function (ev) {
+ lastScrollY = this.scrollTop;
+ lastScrollX = this.scrollLeft;
+ requestTick();
+ });
- function ColumnsByPin(cols) {
- var ret = {
- left: [],
- center: [],
- right: []
- };
+ $scope.$on('$destroy', function () {
+ parent.off('scroll');
+ });
- for (var i = 0, len = cols.length; i < len; i++) {
- var c = cols[i];
- if (c.frozenLeft) {
- ret.left.push(c);
- } else if (c.frozenRight) {
- ret.right.push(c);
- } else {
- ret.center.push(c);
+ $scope.scrollerStyles = function () {
+ if (ctrl.options.scrollbarV) {
+ return {
+ height: ctrl.count * ctrl.options.rowHeight + 'px'
+ };
+ }
+ };
}
- }
-
- return ret;
+ };
}
- function GetTotalFlexGrow(columns) {
- var totalFlexGrow = 0;
-
- var _iteratorNormalCompletion = true;
- var _didIteratorError = false;
- var _iteratorError = undefined;
+ var KEYS = {
+ BACKSPACE: 8,
+ TAB: 9,
+ RETURN: 13,
+ ALT: 18,
+ ESC: 27,
+ SPACE: 32,
+ PAGE_UP: 33,
+ PAGE_DOWN: 34,
+ END: 35,
+ HOME: 36,
+ LEFT: 37,
+ UP: 38,
+ RIGHT: 39,
+ DOWN: 40,
+ DELETE: 46,
+ COMMA: 188,
+ PERIOD: 190,
+ A: 65,
+ Z: 90,
+ ZERO: 48,
+ NUMPAD_0: 96,
+ NUMPAD_9: 105
+ };
- try {
- for (var _iterator = columns[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
- var c = _step.value;
+ var SelectionController = function () {
+ function SelectionController($scope) {
+ _classCallCheck(this, SelectionController);
- totalFlexGrow += c.flexGrow || 0;
- }
- } catch (err) {
- _didIteratorError = true;
- _iteratorError = err;
- } finally {
- try {
- if (!_iteratorNormalCompletion && _iterator.return) {
- _iterator.return();
- }
- } finally {
- if (_didIteratorError) {
- throw _iteratorError;
- }
- }
+ this.body = $scope.body;
+ this.options = $scope.body.options;
+ this.selected = $scope.body.selected;
}
- return totalFlexGrow;
- }
+ _createClass(SelectionController, [{
+ key: "keyDown",
+ value: function keyDown(ev, index, row) {
+ if (KEYS[ev.keyCode]) {
+ ev.preventDefault();
+ }
- function ColumnTotalWidth(columns, prop) {
- var totalWidth = 0;
+ if (ev.keyCode === KEYS.DOWN) {
+ var next = ev.target.nextElementSibling;
+ if (next) {
+ next.focus();
+ }
+ } else if (ev.keyCode === KEYS.UP) {
+ var prev = ev.target.previousElementSibling;
+ if (prev) {
+ prev.focus();
+ }
+ } else if (ev.keyCode === KEYS.RETURN) {
+ this.selectRow(index, row);
+ }
+ }
+ }, {
+ key: "rowClicked",
+ value: function rowClicked(event, index, row) {
+ if (!this.options.checkboxSelection) {
+ this.selectRow(event, index, row);
+ }
- columns.forEach(function (c) {
- var has = prop && c[prop];
- totalWidth = totalWidth + (has ? c[prop] : c.width);
- });
+ this.body.onRowClick({ row: row });
+ }
+ }, {
+ key: "rowDblClicked",
+ value: function rowDblClicked(event, index, row) {
+ if (!this.options.checkboxSelection) {
+ event.preventDefault();
+ this.selectRow(event, index, row);
+ }
- return totalWidth;
- }
+ this.body.onRowDblClick({ row: row });
+ }
+ }, {
+ key: "onCheckboxChange",
+ value: function onCheckboxChange(event, index, row) {
+ this.selectRow(event, index, row);
+ }
+ }, {
+ key: "selectRow",
+ value: function selectRow(event, index, row) {
+ if (this.options.selectable) {
+ if (this.options.multiSelect) {
+ var isCtrlKeyDown = event.ctrlKey || event.metaKey,
+ isShiftKeyDown = event.shiftKey;
- function AdjustColumnWidths(allColumns, expectedWidth) {
- var columnsWidth = ColumnTotalWidth(allColumns),
- totalFlexGrow = GetTotalFlexGrow(allColumns),
- colsByGroup = ColumnsByPin(allColumns);
+ if (isShiftKeyDown) {
+ this.selectRowsBetween(index, row);
+ } else {
+ var idx = this.selected.indexOf(row);
+ if (idx > -1) {
+ this.selected.splice(idx, 1);
+ } else {
+ if (this.options.multiSelectOnShift && this.selected.length === 1) {
+ this.selected.splice(0, 1);
+ }
+ this.selected.push(row);
+ this.body.onSelect({ rows: [row] });
+ }
+ }
+ this.prevIndex = index;
+ } else {
+ this.selected = row;
+ this.body.onSelect({ rows: [row] });
+ }
+ }
+ }
+ }, {
+ key: "selectRowsBetween",
+ value: function selectRowsBetween(index) {
+ var reverse = index < this.prevIndex,
+ selecteds = [];
- if (columnsWidth !== expectedWidth) {
- ScaleColumns(colsByGroup, expectedWidth, totalFlexGrow);
- }
- }
+ for (var i = 0, len = this.body.rows.length; i < len; i++) {
+ var row = this.body.rows[i],
+ greater = i >= this.prevIndex && i <= index,
+ lesser = i <= this.prevIndex && i >= index;
- function ForceFillColumnWidths(allColumns, expectedWidth, startIdx) {
- var contentWidth = 0,
- columnsToResize = startIdx > -1 ? allColumns.slice(startIdx, allColumns.length).filter(function (c) {
- return c.canAutoResize;
- }) : allColumns.filter(function (c) {
- return c.canAutoResize;
- });
+ var range = {};
+ if (reverse) {
+ range = {
+ start: index,
+ end: this.prevIndex - index
+ };
+ } else {
+ range = {
+ start: this.prevIndex,
+ end: index + 1
+ };
+ }
- allColumns.forEach(function (c) {
- if (!c.canAutoResize) {
- contentWidth += c.width;
- } else {
- contentWidth += c.$$oldWidth || c.width;
- }
- });
+ if (reverse && lesser || !reverse && greater) {
+ var idx = this.selected.indexOf(row);
- var remainingWidth = expectedWidth - contentWidth,
- additionWidthPerColumn = remainingWidth / columnsToResize.length,
- exceedsWindow = contentWidth > expectedWidth;
+ if (reverse && idx > -1) {
+ this.selected.splice(idx, 1);
+ continue;
+ }
- columnsToResize.forEach(function (column) {
- if (exceedsWindow) {
- column.width = column.$$oldWidth || column.width;
- } else {
- if (!column.$$oldWidth) {
- column.$$oldWidth = column.width;
+ if (i >= range.start && i < range.end) {
+ if (idx === -1) {
+ this.selected.push(row);
+ selecteds.push(row);
+ }
+ }
+ }
}
- var newSize = column.$$oldWidth + additionWidthPerColumn;
- if (column.minWith && newSize < column.minWidth) {
- column.width = column.minWidth;
- } else if (column.maxWidth && newSize > column.maxWidth) {
- column.width = column.maxWidth;
- } else {
- column.width = newSize;
- }
+ this.body.onSelect({ rows: selecteds });
}
- });
- }
+ }]);
- function ColumnGroupWidths(groups, all) {
+ return SelectionController;
+ }();
+
+ function SelectionDirective() {
return {
- left: ColumnTotalWidth(groups.left),
- center: ColumnTotalWidth(groups.center),
- right: ColumnTotalWidth(groups.right),
- total: ColumnTotalWidth(all)
+ controller: SelectionController,
+ restrict: 'A',
+ require: '^dtBody',
+ controllerAs: 'selCtrl'
};
}
- var ColumnDefaults = {
- frozenLeft: false,
-
- frozenRight: false,
-
- className: undefined,
-
- headerClassName: undefined,
-
- flexGrow: 0,
-
- minWidth: 100,
-
- maxWidth: undefined,
-
- width: 150,
-
- resizable: true,
-
- comparator: undefined,
-
- sortable: true,
-
- sort: undefined,
-
- sortBy: undefined,
-
- headerRenderer: undefined,
-
- cellRenderer: undefined,
+ var RowController = function () {
+ function RowController() {
+ _classCallCheck(this, RowController);
+ }
- cellDataGetter: undefined,
+ _createClass(RowController, [{
+ key: "getValue",
+ value: function getValue(col) {
+ if (!col.prop) return '';
+ return DeepValueGetter(this.row, col.prop);
+ }
+ }, {
+ key: "onTreeToggled",
+ value: function onTreeToggled(cell) {
+ this.onTreeToggle({
+ cell: cell,
+ row: this.row
+ });
+ }
+ }, {
+ key: "stylesByGroup",
+ value: function stylesByGroup(group) {
+ var styles = {
+ width: this.columnWidths[group] + 'px'
+ };
- isTreeColumn: false,
+ if (group === 'left') {
+ TranslateXY(styles, this.options.internal.offsetX, 0);
+ } else if (group === 'right') {
+ var offset = (this.columnWidths.total - this.options.internal.innerWidth - this.options.internal.offsetX + this.options.internal.scrollBarWidth) * -1;
+ TranslateXY(styles, offset, 0);
+ }
- isCheckboxColumn: false,
+ return styles;
+ }
+ }, {
+ key: "onCheckboxChanged",
+ value: function onCheckboxChanged(ev) {
+ this.onCheckboxChange({
+ $event: ev,
+ row: this.row
+ });
+ }
+ }]);
- headerCheckbox: false,
+ return RowController;
+ }();
- canAutoResize: true
+ function RowDirective() {
+ return {
+ restrict: 'E',
+ controller: RowController,
+ controllerAs: 'rowCtrl',
+ scope: true,
+ bindToController: {
+ row: '=',
+ columns: '=',
+ columnWidths: '=',
+ expanded: '=',
+ selected: '=',
+ hasChildren: '=',
+ options: '=',
+ onCheckboxChange: '&',
+ onTreeToggle: '&'
+ },
+ link: function link($scope, $elm, $attrs, ctrl) {
+ if (ctrl.row) {
+ TranslateXY($elm[0].style, 0, ctrl.row.$$index * ctrl.options.rowHeight);
+ }
- };
+ ctrl.options.internal.styleTranslator.register($scope.$index, $elm);
+ },
+ template: "\n \n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
",
+ replace: true
+ };
+ }
- var TableDefaults = {
- scrollbarV: true,
+ var GroupRowController = function () {
+ function GroupRowController() {
+ _classCallCheck(this, GroupRowController);
+ }
- rowHeight: 30,
+ _createClass(GroupRowController, [{
+ key: "onGroupToggled",
+ value: function onGroupToggled(evt) {
+ evt.stopPropagation();
+ this.onGroupToggle({
+ group: this.row
+ });
+ }
+ }, {
+ key: "treeClass",
+ value: function treeClass() {
+ return {
+ 'dt-tree-toggle': true,
+ 'icon-right': !this.expanded,
+ 'icon-down': this.expanded
+ };
+ }
+ }]);
- columnMode: 'standard',
+ return GroupRowController;
+ }();
- loadingMessage: 'Loading...',
+ function GroupRowDirective() {
+ return {
+ restrict: 'E',
+ controller: GroupRowController,
+ controllerAs: 'group',
+ bindToController: {
+ row: '=',
+ onGroupToggle: '&',
+ expanded: '=',
+ options: '='
+ },
+ scope: true,
+ replace: true,
+ template: "\n \n \n \n \n \n
",
+ link: function link($scope, $elm, $attrs, ctrl) {
+ TranslateXY($elm[0].style, 0, ctrl.row.$$index * ctrl.options.rowHeight);
- emptyMessage: 'No data to display',
+ ctrl.options.internal.styleTranslator.register($scope.$index, $elm);
+ }
+ };
+ }
- headerHeight: 30,
+ var CellController = function () {
+ function CellController() {
+ _classCallCheck(this, CellController);
+ }
- footerHeight: 0,
+ _createClass(CellController, [{
+ key: "styles",
+ value: function styles() {
+ return {
+ width: this.column.width + 'px',
+ 'min-width': this.column.width + 'px'
+ };
+ }
+ }, {
+ key: "cellClass",
+ value: function cellClass() {
+ var style = {
+ 'dt-tree-col': this.column.isTreeColumn
+ };
- paging: {
- externalPaging: false,
+ if (this.column.className) {
+ style[this.column.className] = true;
+ }
- size: undefined,
+ return style;
+ }
+ }, {
+ key: "treeClass",
+ value: function treeClass() {
+ return {
+ 'dt-tree-toggle': true,
+ 'icon-right': !this.expanded,
+ 'icon-down': this.expanded
+ };
+ }
+ }, {
+ key: "onTreeToggled",
+ value: function onTreeToggled(evt) {
+ evt.stopPropagation();
+ this.expanded = !this.expanded;
+ this.onTreeToggle({
+ cell: {
+ value: this.value,
+ column: this.column,
+ expanded: this.expanded
+ }
+ });
+ }
+ }, {
+ key: "onCheckboxChanged",
+ value: function onCheckboxChanged(event) {
+ event.stopPropagation();
+ this.onCheckboxChange({ $event: event });
+ }
+ }, {
+ key: "getValue",
+ value: function getValue() {
+ var val = this.column.cellDataGetter ? this.column.cellDataGetter(this.value) : this.value;
- count: 0,
+ if (val === undefined || val === null) val = '';
+ return val;
+ }
+ }]);
- offset: 0,
+ return CellController;
+ }();
- loadingIndicator: false
- },
+ function CellDirective($rootScope, $compile, $log, $timeout) {
+ return {
+ restrict: 'E',
+ controller: CellController,
+ scope: true,
+ controllerAs: 'cell',
+ bindToController: {
+ options: '=',
+ value: '=',
+ selected: '=',
+ column: '=',
+ row: '=',
+ expanded: '=',
+ hasChildren: '=',
+ onTreeToggle: '&',
+ onCheckboxChange: '&'
+ },
+ template: "\n \n \n \n \n \n
",
+ replace: true,
+ compile: function compile() {
+ return {
+ pre: function pre($scope, $elm, $attrs, ctrl) {
+ var content = _angular2.default.element($elm[0].querySelector('.dt-cell-content')),
+ cellScope;
- selectable: false,
+ if (ctrl.column.template || ctrl.column.cellRenderer) {
+ createCellScope();
+ }
- multiSelect: false,
+ $scope.$watch('cell.row', function () {
+ if (cellScope) {
+ cellScope.$destroy();
- checkboxSelection: false,
+ createCellScope();
- reorderable: true,
+ cellScope.$cell = ctrl.value;
+ cellScope.$row = ctrl.row;
+ cellScope.$column = ctrl.column;
+ cellScope.$$watchers = null;
+ }
- internal: {
- offsetX: 0,
- offsetY: 0,
- innerWidth: 0,
- bodyHeight: 300
- }
+ if (ctrl.column.template) {
+ content.empty();
+ var elm = _angular2.default.element("" + ctrl.column.template.trim() + " ");
+ content.append($compile(elm)(cellScope));
+ } else if (ctrl.column.cellRenderer) {
+ content.empty();
+ var elm = _angular2.default.element(ctrl.column.cellRenderer(cellScope, content));
+ content.append($compile(elm)(cellScope));
+ } else {
+ content[0].innerHTML = ctrl.getValue();
+ }
+ }, true);
- };
+ function createCellScope() {
+ cellScope = ctrl.options.$outer.$new(false);
+ cellScope.getValue = ctrl.getValue;
+ }
+ }
+ };
+ }
+ };
+ }
- var DataTableController = function () {
- DataTableController.$inject = ["$scope", "$filter", "$log", "$transclude"];
- function DataTableController($scope, $filter, $log, $transclude) {
+ var FooterController = function () {
+ function FooterController($scope) {
var _this6 = this;
- _classCallCheck(this, DataTableController);
+ _classCallCheck(this, FooterController);
- Object.assign(this, {
- $scope: $scope,
- $filter: $filter,
- $log: $log
+ this.page = this.paging.offset + 1;
+ $scope.$watch('footer.paging.offset', function (newVal) {
+ _this6.offsetChanged(newVal);
});
+ }
- this.defaults();
+ _createClass(FooterController, [{
+ key: "offsetChanged",
+ value: function offsetChanged(newVal) {
+ this.page = newVal + 1;
+ }
+ }, {
+ key: "onPaged",
+ value: function onPaged(page) {
+ this.paging.offset = page - 1;
+ this.onPage({
+ offset: this.paging.offset,
+ size: this.paging.size
+ });
+ }
+ }]);
- this.options.$outer = $scope.$parent;
+ return FooterController;
+ }();
- $scope.$watch('dt.options.columns', function (newVal, oldVal) {
- _this6.transposeColumnDefaults();
+ function FooterDirective() {
+ return {
+ restrict: 'E',
+ controller: FooterController,
+ controllerAs: 'footer',
+ scope: true,
+ bindToController: {
+ paging: '=',
+ onPage: '&'
+ },
+ template: "",
+ replace: true
+ };
+ }
- if (newVal.length !== oldVal.length) {
- _this6.adjustColumns();
- }
+ var PagerController = function () {
+ function PagerController($scope) {
+ var _this7 = this;
- _this6.calculateColumns();
- }, true);
+ _classCallCheck(this, PagerController);
- var watch = $scope.$watch('dt.rows', function (newVal) {
- if (newVal) {
- watch();
- _this6.onSorted();
- }
+ $scope.$watch('pager.count', function (newVal) {
+ _this7.calcTotalPages(_this7.size, _this7.count);
+ _this7.getPages(_this7.page || 1);
});
- }
-
- _createClass(DataTableController, [{
- key: "defaults",
- value: function defaults() {
- var _this7 = this;
- this.expanded = this.expanded || {};
+ $scope.$watch('pager.size', function (newVal) {
+ _this7.calcTotalPages(_this7.size, _this7.count);
+ _this7.getPages(_this7.page || 1);
+ });
- this.options = angular.extend(angular.copy(TableDefaults), this.options);
+ $scope.$watch('pager.page', function (newVal) {
+ if (newVal !== 0 && newVal <= _this7.totalPages) {
+ _this7.getPages(newVal);
+ }
+ });
- angular.forEach(TableDefaults.paging, function (v, k) {
- if (!_this7.options.paging[k]) {
- _this7.options.paging[k] = v;
- }
- });
+ this.getPages(this.page || 1);
+ }
- if (this.options.selectable && this.options.multiSelect) {
- this.selected = this.selected || [];
- }
+ _createClass(PagerController, [{
+ key: "calcTotalPages",
+ value: function calcTotalPages(size, count) {
+ var count = size < 1 ? 1 : Math.ceil(count / size);
+ this.totalPages = Math.max(count || 0, 1);
}
}, {
- key: "transposeColumnDefaults",
- value: function transposeColumnDefaults() {
- for (var i = 0, len = this.options.columns.length; i < len; i++) {
- var column = this.options.columns[i];
- column.$id = ObjectId();
-
- angular.forEach(ColumnDefaults, function (v, k) {
- if (!column.hasOwnProperty(k)) {
- column[k] = v;
- }
+ key: "selectPage",
+ value: function selectPage(num) {
+ if (num > 0 && num <= this.totalPages) {
+ this.page = num;
+ this.onPage({
+ page: num
});
-
- if (column.name && !column.prop) {
- column.prop = CamelCase(column.name);
- }
-
- this.options.columns[i] = column;
}
}
}, {
- key: "calculateColumns",
- value: function calculateColumns() {
- var columns = this.options.columns;
- this.columnsByPin = ColumnsByPin(columns);
- this.columnWidths = ColumnGroupWidths(this.columnsByPin, columns);
+ key: "prevPage",
+ value: function prevPage() {
+ if (this.page > 1) {
+ this.selectPage(--this.page);
+ }
}
}, {
- key: "tableCss",
- value: function tableCss() {
- return {
- 'fixed': this.options.scrollbarV,
- 'selectable': this.options.selectable,
- 'checkboxable': this.options.checkboxSelection
- };
+ key: "nextPage",
+ value: function nextPage() {
+ this.selectPage(++this.page);
}
}, {
- key: "adjustColumns",
- value: function adjustColumns(forceIdx) {
- var width = this.options.internal.innerWidth - this.options.internal.scrollBarWidth;
-
- if (this.options.columnMode === 'force') {
- ForceFillColumnWidths(this.options.columns, width, forceIdx);
- } else if (this.options.columnMode === 'flex') {
- AdjustColumnWidths(this.options.columns, width);
- }
+ key: "canPrevious",
+ value: function canPrevious() {
+ return this.page > 1;
}
}, {
- key: "calculatePageSize",
- value: function calculatePageSize() {
- this.options.paging.size = Math.ceil(this.options.internal.bodyHeight / this.options.rowHeight) + 1;
+ key: "canNext",
+ value: function canNext() {
+ return this.page < this.totalPages;
}
}, {
- key: "onSorted",
- value: function onSorted() {
- if (!this.rows) return;
+ key: "getPages",
+ value: function getPages(page) {
+ var pages = [],
+ startPage = 1,
+ endPage = this.totalPages,
+ maxSize = 5,
+ isMaxSized = maxSize < this.totalPages;
- var sorts = this.options.columns.filter(function (c) {
- return c.sort;
- }).sort(function (a, b) {
- if (a.sortPriority && b.sortPriority) {
- if (a.sortPriority > b.sortPriority) return 1;
- if (a.sortPriority < b.sortPriority) return -1;
- } else if (a.sortPriority) {
- return -1;
- } else if (b.sortPriority) {
- return 1;
- }
+ if (isMaxSized) {
+ startPage = (Math.ceil(page / maxSize) - 1) * maxSize + 1;
+ endPage = Math.min(startPage + maxSize - 1, this.totalPages);
+ }
- return 0;
- }).map(function (c, i) {
- c.sortPriority = i + 1;
- return c;
- });
+ for (var number = startPage; number <= endPage; number++) {
+ pages.push({
+ number: number,
+ text: number,
+ active: number === page
+ });
+ }
- if (sorts.length) {
- this.onSort({ sorts: sorts });
+ this.pages = pages;
+ }
+ }]);
+
+ return PagerController;
+ }();
+
+ function PagerDirective() {
+ return {
+ restrict: 'E',
+ controller: PagerController,
+ controllerAs: 'pager',
+ scope: true,
+ bindToController: {
+ page: '=',
+ size: '=',
+ count: '=',
+ onPage: '&'
+ },
+ template: "",
+ replace: true
+ };
+ }
+
+ function PopoverDirective($q, $timeout, $templateCache, $compile, PopoverRegistry, PositionHelper, $animate) {
+ function loadTemplate(template, plain) {
+ if (!template) {
+ return '';
+ }
+
+ if (_angular2.default.isString(template) && plain) {
+ return template;
+ }
+
+ return $templateCache.get(template) || $http.get(template, { cache: true });
+ }
+
+ function toBoolean(value) {
+ if (value && value.length !== 0) {
+ var v = ("" + value).toLowerCase();
+ value = v == 'true';
+ } else {
+ value = false;
+ }
+ return value;
+ }
+
+ return {
+ restrict: 'A',
+ scope: true,
+ replace: false,
+ link: function link($scope, $element, $attributes) {
+ $scope.popover = null;
+ $scope.popoverId = Date.now();
+
+ $scope.options = {
+ text: $attributes.popoverText,
+ template: $attributes.popoverTemplate,
+ plain: toBoolean($attributes.popoverPlain || false),
+ placement: $attributes.popoverPlacement || 'right',
+ alignment: $attributes.popoverAlignment || 'center',
+ group: $attributes.popoverGroup,
+ spacing: parseInt($attributes.popoverSpacing) || 0,
+ showCaret: toBoolean($attributes.popoverPlain || false)
+ };
+
+ $element.off('mouseenter', display);
+ $element.on('mouseenter', display);
+ $element.off('mouseleave', mouseOut);
+ $element.on('mouseleave', mouseOut);
+
+ function mouseOut() {
+ $scope.exitTimeout = $timeout(remove, 500);
+ }
+
+ function display() {
+ $timeout.cancel($scope.exitTimeout);
+
+ var elm = document.getElementById("#" + $scope.popoverId);
+ if ($scope.popover && elm) return;
- if (this.options.onSort) {
- this.options.onSort(sorts);
+ if ($scope.options.group) {
+ PopoverRegistry.removeGroup($scope.options.group, $scope.popoverId);
}
- var clientSorts = [];
- for (var i = 0, len = sorts.length; i < len; i++) {
- var c = sorts[i];
- if (c.comparator !== false) {
- var dir = c.sort === 'asc' ? '' : '-';
- if (c.sortBy !== undefined) {
- clientSorts.push(dir + c.sortBy);
- } else {
- clientSorts.push(dir + c.prop);
+ if ($scope.options.text && !$scope.options.template) {
+ $scope.popover = _angular2.default.element("
");
+
+ $scope.popover.html($scope.options.text);
+ _angular2.default.element(document.body).append($scope.popover);
+ positionPopover($element, $scope.popover, $scope.options);
+ PopoverRegistry.add($scope.popoverId, { element: $element, popover: $scope.popover, group: $scope.options.group });
+ } else {
+ $q.when(loadTemplate($scope.options.template, $scope.options.plain)).then(function (template) {
+ if (!_angular2.default.isString(template)) {
+ if (template.data && _angular2.default.isString(template.data)) {
+ template = template.data;
+ } else {
+ template = '';
+ }
}
- }
- }
- if (clientSorts.length) {
- var _rows;
+ $scope.popover = _angular2.default.element("
");
- var sortedValues = this.$filter('orderBy')(this.rows, clientSorts);
- this.rows.splice(0, this.rows.length);
- (_rows = this.rows).push.apply(_rows, _toConsumableArray(sortedValues));
+ $scope.popover.html(template);
+ $compile($scope.popover)($scope);
+ _angular2.default.element(document.body).append($scope.popover);
+ positionPopover($element, $scope.popover, $scope.options);
+
+ $scope.popover.off('mouseleave', mouseOut);
+ $scope.popover.on('mouseleave', mouseOut);
+ $scope.popover.on('mouseenter', function () {
+ $timeout.cancel($scope.exitTimeout);
+ });
+
+ PopoverRegistry.add($scope.popoverId, {
+ element: $element,
+ popover: $scope.popover,
+ group: $scope.options.group
+ });
+ });
}
}
- this.options.internal.setYOffset(0);
- }
- }, {
- key: "onTreeToggled",
- value: function onTreeToggled(row, cell) {
- this.onTreeToggle({
- row: row,
- cell: cell
- });
- }
- }, {
- key: "onBodyPage",
- value: function onBodyPage(offset, size) {
- this.onPage({
- offset: offset,
- size: size
- });
- }
- }, {
- key: "onFooterPage",
- value: function onFooterPage(offset, size) {
- var pageBlockSize = this.options.rowHeight * size,
- offsetY = pageBlockSize * offset;
+ function remove() {
+ if ($scope.popover) {
+ $scope.popover.remove();
+ }
- this.options.internal.setYOffset(offsetY);
- }
- }, {
- key: "onHeaderCheckboxChange",
- value: function onHeaderCheckboxChange() {
- if (this.rows) {
- var matches = this.selected.length === this.rows.length;
- this.selected.splice(0, this.selected.length);
+ $scope.popover = undefined;
+ PopoverRegistry.remove($scope.popoverId);
+ }
- if (!matches) {
- var _selected;
+ function positionPopover(triggerElement, popover, options) {
+ $timeout(function () {
+ var elDimensions = triggerElement[0].getBoundingClientRect(),
+ popoverDimensions = popover[0].getBoundingClientRect(),
+ top,
+ left;
+
+ if (options.placement === 'right') {
+ left = elDimensions.left + elDimensions.width + options.spacing;
+ top = PositionHelper.calculateVerticalAlignment(elDimensions, popoverDimensions, options.alignment);
+ }
+ if (options.placement === 'left') {
+ left = elDimensions.left - popoverDimensions.width - options.spacing;
+ top = PositionHelper.calculateVerticalAlignment(elDimensions, popoverDimensions, options.alignment);
+ }
+ if (options.placement === 'top') {
+ top = elDimensions.top - popoverDimensions.height - options.spacing;
+ left = PositionHelper.calculateHorizontalAlignment(elDimensions, popoverDimensions, options.alignment);
+ }
+ if (options.placement === 'bottom') {
+ top = elDimensions.top + elDimensions.height + options.spacing;
+ left = PositionHelper.calculateHorizontalAlignment(elDimensions, popoverDimensions, options.alignment);
+ }
- (_selected = this.selected).push.apply(_selected, _toConsumableArray(this.rows));
+ popover.css({
+ top: top + 'px',
+ left: left + 'px'
+ });
+
+ if ($scope.options.showCaret) {
+ addCaret($scope.popover, elDimensions, popoverDimensions);
+ }
+
+ $animate.addClass($scope.popover, 'popover-animation');
+ }, 50);
+ }
+
+ function addCaret(popoverEl, elDimensions, popoverDimensions) {
+ var caret = _angular2.default.element(" ");
+ popoverEl.append(caret);
+ var caretDimensions = caret[0].getBoundingClientRect();
+
+ var left, top;
+ if ($scope.options.placement === 'right') {
+ left = -6;
+ top = PositionHelper.calculateVerticalCaret(elDimensions, popoverDimensions, caretDimensions, $scope.options.alignment);
}
+ if ($scope.options.placement === 'left') {
+ left = popoverDimensions.width - 2;
+ top = PositionHelper.calculateVerticalCaret(elDimensions, popoverDimensions, caretDimensions, $scope.options.alignment);
+ }
+ if ($scope.options.placement === 'top') {
+ top = popoverDimensions.height - 5;
+ left = PositionHelper.calculateHorizontalCaret(elDimensions, popoverDimensions, caretDimensions, $scope.options.alignment);
+ }
+
+ if ($scope.options.placement === 'bottom') {
+ top = -8;
+ left = PositionHelper.calculateHorizontalCaret(elDimensions, popoverDimensions, caretDimensions, $scope.options.alignment);
+ }
+
+ caret.css({
+ top: top + 'px',
+ left: left + 'px'
+ });
}
}
- }, {
- key: "isAllRowsSelected",
- value: function isAllRowsSelected() {
- if (this.rows) return false;
- return this.selected.length === this.rows.length;
- }
- }, {
- key: "onResized",
- value: function onResized(column, width) {
- var idx = this.options.columns.indexOf(column);
- if (idx > -1) {
- var column = this.options.columns[idx];
- column.width = width;
- column.canAutoResize = false;
+ };
+ }
- this.adjustColumns(idx);
- this.calculateColumns();
+ function PopoverRegistry($animate) {
+ var popovers = {};
+ this.add = function (id, object) {
+ popovers[id] = object;
+ };
+ this.find = function (id) {
+ popovers[id];
+ };
+ this.remove = function (id) {
+ delete popovers[id];
+ };
+ this.removeGroup = function (group, currentId) {
+ angular.forEach(popovers, function (popoverOb, id) {
+ if (id === currentId) return;
+
+ if (popoverOb.group && popoverOb.group === group) {
+ $animate.removeClass(popoverOb.popover, 'sw-popover-animate').then(function () {
+ popoverOb.popover.remove();
+ delete popovers[id];
+ });
}
+ });
+ };
+ }
- if (this.onColumnResize) {
- this.onColumnResize({
- column: column,
- width: width
- });
+ function PositionHelper() {
+ return {
+
+ calculateVerticalAlignment: function calculateVerticalAlignment(elDimensions, popoverDimensions, alignment) {
+ if (alignment === 'top') {
+ return elDimensions.top;
+ }
+ if (alignment === 'bottom') {
+ return elDimensions.top + elDimensions.height - popoverDimensions.height;
+ }
+ if (alignment === 'center') {
+ return elDimensions.top + elDimensions.height / 2 - popoverDimensions.height / 2;
+ }
+ },
+
+ calculateVerticalCaret: function calculateVerticalCaret(elDimensions, popoverDimensions, caretDimensions, alignment) {
+ if (alignment === 'top') {
+ return elDimensions.height / 2 - caretDimensions.height / 2 - 1;
+ }
+ if (alignment === 'bottom') {
+ return popoverDimensions.height - elDimensions.height / 2 - caretDimensions.height / 2 - 1;
+ }
+ if (alignment === 'center') {
+ return popoverDimensions.height / 2 - caretDimensions.height / 2 - 1;
+ }
+ },
+
+ calculateHorizontalCaret: function calculateHorizontalCaret(elDimensions, popoverDimensions, caretDimensions, alignment) {
+ if (alignment === 'left') {
+ return elDimensions.width / 2 - caretDimensions.height / 2 - 1;
+ }
+ if (alignment === 'right') {
+ return popoverDimensions.width - elDimensions.width / 2 - caretDimensions.height / 2 - 1;
+ }
+ if (alignment === 'center') {
+ return popoverDimensions.width / 2 - caretDimensions.height / 2 - 1;
+ }
+ },
+
+ calculateHorizontalAlignment: function calculateHorizontalAlignment(elDimensions, popoverDimensions, alignment) {
+ if (alignment === 'left') {
+ return elDimensions.left;
+ }
+ if (alignment === 'right') {
+ return elDimensions.left + elDimensions.width - popoverDimensions.width;
+ }
+ if (alignment === 'center') {
+ return elDimensions.left + elDimensions.width / 2 - popoverDimensions.width / 2;
}
}
- }, {
- key: "onSelected",
- value: function onSelected(rows) {
- this.onSelect({
- rows: rows
+
+ };
+ }
+
+ var popover = _angular2.default.module('dt.popover', []).service('PopoverRegistry', PopoverRegistry).factory('PositionHelper', PositionHelper).directive('popover', PopoverDirective);
+
+ var MenuController = function () {
+ function MenuController($scope, $timeout) {
+ _classCallCheck(this, MenuController);
+
+ this.$scope = $scope;
+ }
+
+ _createClass(MenuController, [{
+ key: "getColumnIndex",
+ value: function getColumnIndex(model) {
+ return this.$scope.current.findIndex(function (col) {
+ return model.name == col.name;
});
}
}, {
- key: "onRowClicked",
- value: function onRowClicked(row) {
- this.onRowClick({
- row: row
- });
+ key: "isChecked",
+ value: function isChecked(model) {
+ return this.getColumnIndex(model) > -1;
}
}, {
- key: "onRowDblClicked",
- value: function onRowDblClicked(row) {
- this.onRowDblClick({
- row: row
- });
+ key: "onCheck",
+ value: function onCheck(model) {
+ var idx = this.getColumnIndex(model);
+ if (idx === -1) {
+ this.$scope.current.push(model);
+ } else {
+ this.$scope.current.splice(idx, 1);
+ }
}
}]);
- return DataTableController;
+ return MenuController;
}();
- function DataTableDirective($window, $timeout, $parse) {
+ function MenuDirective() {
return {
restrict: 'E',
- replace: true,
- controller: DataTableController,
- scope: true,
- bindToController: {
- options: '=',
- rows: '=',
- selected: '=?',
- expanded: '=?',
- onSelect: '&',
- onSort: '&',
- onTreeToggle: '&',
- onPage: '&',
- onRowClick: '&',
- onRowDblClick: '&',
- onColumnResize: '&'
+ controller: 'MenuController',
+ controllerAs: 'dtm',
+ scope: {
+ current: '=',
+ available: '='
},
- controllerAs: 'dt',
- template: function template(element) {
- var columns = element[0].getElementsByTagName('column'),
- id = ObjectId();
- DataTableService.saveColumns(id, columns);
+ template: ""
+ };
+ }
- return "\n \n \n \n \n \n \n
";
- },
- compile: function compile(tElem, tAttrs) {
- return {
- pre: function pre($scope, $elm, $attrs, ctrl) {
- DataTableService.buildColumns($scope, $parse);
+ var DropdownController = function () {
+ function DropdownController($scope) {
+ _classCallCheck(this, DropdownController);
- var id = $elm.attr('data-column-id'),
- columns = DataTableService.columns[id];
- if (columns) {
- ctrl.options.columns = columns;
- }
+ $scope.open = false;
+ }
- ctrl.transposeColumnDefaults();
- ctrl.options.internal.scrollBarWidth = ScrollbarWidth();
+ _createClass(DropdownController, [{
+ key: "toggle",
+ value: function toggle(scope) {
+ scope.open = !scope.open;
+ }
+ }]);
- function resize() {
- var rect = $elm[0].getBoundingClientRect();
+ return DropdownController;
+ }();
- ctrl.options.internal.innerWidth = Math.floor(rect.width);
+ function DropdownDirective($document, $timeout) {
+ return {
+ restrict: 'C',
+ controller: 'DropdownController',
+ link: function link($scope, $elm, $attrs) {
- if (ctrl.options.scrollbarV) {
- var height = rect.height;
+ function closeDropdown(ev) {
+ if ($elm[0].contains(ev.target)) {
+ return;
+ }
- if (ctrl.options.headerHeight) {
- height = height - ctrl.options.headerHeight;
- }
+ $timeout(function () {
+ $scope.open = false;
+ off();
+ });
+ }
- if (ctrl.options.footerHeight) {
- height = height - ctrl.options.footerHeight;
- }
+ function keydown(ev) {
+ if (ev.which === 27) {
+ $timeout(function () {
+ $scope.open = false;
+ off();
+ });
+ }
+ }
- ctrl.options.internal.bodyHeight = height;
- ctrl.calculatePageSize();
- }
+ function off() {
+ $document.unbind('click', closeDropdown);
+ $document.unbind('keydown', keydown);
+ }
- ctrl.adjustColumns();
- };
+ $scope.$watch('open', function (newVal) {
+ if (newVal) {
+ $document.bind('click', closeDropdown);
+ $document.bind('keydown', keydown);
+ }
+ });
+ }
+ };
+ }
- $window.addEventListener('resize', throttle(function () {
- $timeout(resize);
- }));
+ function DropdownToggleDirective($timeout) {
+ return {
+ restrict: 'C',
+ controller: 'DropdownController',
+ require: '?^dropdown',
+ link: function link($scope, $elm, $attrs, ctrl) {
- var checkVisibility = function checkVisibility() {
- var bounds = $elm[0].getBoundingClientRect(),
- visible = bounds.width && bounds.height;
- if (visible) resize();else $timeout(checkVisibility, 100);
- };
- checkVisibility();
+ function toggleClick(event) {
+ event.preventDefault();
+ $timeout(function () {
+ ctrl.toggle($scope);
+ });
+ }
- $elm.addClass('dt-loaded');
+ function toggleDestroy() {
+ $elm.unbind('click', toggleClick);
+ }
- $scope.$on('$destroy', function () {
- angular.element($window).off('resize');
- });
- }
- };
+ $elm.bind('click', toggleClick);
+ $scope.$on('$destroy', toggleDestroy);
+ }
+ };
+ }
+
+ function DropdownMenuDirective($animate) {
+ return {
+ restrict: 'C',
+ require: '?^dropdown',
+ link: function link($scope, $elm, $attrs, ctrl) {
+ $scope.$watch('open', function () {
+ $animate[$scope.open ? 'addClass' : 'removeClass']($elm, 'ddm-open');
+ });
}
};
}
- var dataTable = angular.module('data-table', []).directive('dtable', DataTableDirective).directive('resizable', ResizableDirective).directive('sortable', SortableDirective).directive('dtHeader', HeaderDirective).directive('dtHeaderCell', HeaderCellDirective).directive('dtBody', BodyDirective).directive('dtScroller', ScrollerDirective).directive('dtSeletion', SelectionDirective).directive('dtRow', RowDirective).directive('dtGroupRow', GroupRowDirective).directive('dtCell', CellDirective).directive('dtFooter', FooterDirective).directive('dtPager', PagerDirective);
+ var dropdown = _angular2.default.module('dt.dropdown', []).controller('DropdownController', DropdownController).directive('dropdown', DropdownDirective).directive('dropdownToggle', DropdownToggleDirective).directive('dropdownMenu', DropdownMenuDirective);
+
+ var menu = _angular2.default.module('dt.menu', [dropdown.name]).controller('MenuController', MenuController).directive('dtm', MenuDirective);
+
+ var dataTable = _angular2.default.module('data-table', []).directive('dtable', DataTableDirective).directive('resizable', ResizableDirective).directive('sortable', SortableDirective).directive('dtHeader', HeaderDirective).directive('dtHeaderCell', HeaderCellDirective).directive('dtBody', BodyDirective).directive('dtScroller', ScrollerDirective).directive('dtSeletion', SelectionDirective).directive('dtRow', RowDirective).directive('dtGroupRow', GroupRowDirective).directive('dtCell', CellDirective).directive('dtFooter', FooterDirective).directive('dtPager', PagerDirective);
+ exports.dtPopover = popover;
+ exports.dtMenu = menu;
exports.default = dataTable;
});
\ No newline at end of file
diff --git a/release/dataTable.min.js b/release/dataTable.min.js
index a01c68b..76e21e8 100644
--- a/release/dataTable.min.js
+++ b/release/dataTable.min.js
@@ -4,5 +4,5 @@
* @link http://swimlane.com/
* @license
*/
-!function(e,t){if("function"==typeof define&&define.amd)define("DataTable",["exports"],t);else if("undefined"!=typeof exports)t(exports);else{var n={exports:{}};t(n.exports),e.DataTable=n.exports}}(this,function(e){"use strict";function t(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t\n \n ',replace:!0}}function i(){return{restrict:"E",controller:B,controllerAs:"footer",scope:!0,bindToController:{paging:"=",onPage:"&"},template:'',replace:!0}}function r(e,t,n,o){return{restrict:"E",controller:G,scope:!0,controllerAs:"cell",bindToController:{options:"=",value:"=",selected:"=",column:"=",row:"=",expanded:"=",hasChildren:"=",onTreeToggle:"&",onCheckboxChange:"&"},template:'\n \n \n \n \n \n
',replace:!0,compile:function(){return{pre:function(e,n,o,i){function r(){s=i.options.$outer.$new(!1),s.getValue=i.getValue}var s,l=angular.element(n[0].querySelector(".dt-cell-content"));(i.column.template||i.column.cellRenderer)&&r(),e.$watch("cell.row",function(){if(s&&(s.$destroy(),r(),s.$cell=i.value,s.$row=i.row,s.$column=i.column,s.$$watchers=null),i.column.template){l.empty();var e=angular.element(""+i.column.template.trim()+" ");l.append(t(e)(s))}else if(i.column.cellRenderer){l.empty();var e=angular.element(i.column.cellRenderer(s,l));l.append(t(e)(s))}else l[0].innerHTML=i.getValue()},!0)}}}}}function s(e){return e=e.replace(/[^a-zA-Z0-9 ]/g," "),e=e.replace(/([a-z](?=[A-Z]))/g,"$1 "),e=e.replace(/([^a-zA-Z0-9 ])|^[0-9]+/g,"").trim().toLowerCase(),e=e.replace(/([ 0-9]+)([a-zA-Z])/g,function(e,t,n){return t.trim()+n.toUpperCase()})}function l(e){var t=s(e);return D[t]||(void 0!==H[M.css+e]?D[t]=M.css+e:void 0!==H[e]&&(D[t]=e)),D[t]}function a(e,t,n){V?!I&&j?(e[N]="translate3d("+t+"px, "+n+"px, 0)",e[O]="hidden"):e[s(N)]="translate("+t+"px, "+n+"px)":(e.top=n+"px",e.left=t+"px")}function c(){return{restrict:"E",controller:F,controllerAs:"group",bindToController:{row:"=",onGroupToggle:"&",expanded:"=",options:"="},scope:!0,replace:!0,template:'\n \n \n \n \n \n
',link:function(e,t,n,o){a(t[0].style,0,o.row.$$index*o.options.rowHeight),o.options.internal.styleTranslator.register(e.$index,t)}}}function d(e,t){if(!e||!t)return e;var n=e,o=t.split(".");if(o.length)for(var i=0,r=o.length;r>i;i++)n=n[o[i]];return n}function u(){return{restrict:"E",controller:U,controllerAs:"rowCtrl",scope:!0,bindToController:{row:"=",columns:"=",columnWidths:"=",expanded:"=",selected:"=",hasChildren:"=",options:"=",onCheckboxChange:"&",onTreeToggle:"&"},link:function(e,t,n,o){o.row&&a(t[0].style,0,o.row.$$index*o.options.rowHeight),o.options.internal.styleTranslator.register(e.$index,t)},template:'\n \n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
',replace:!0}}function h(){return{controller:q,restrict:"A",require:"^dtBody",controllerAs:"selCtrl"}}function p(e,t){return{restrict:"E",require:"^dtBody",transclude:!0,replace:!0,template:'
',link:function(e,t,n,o){function i(){o.options.internal.offsetY=l,o.options.internal.offsetX=a,o.updatePage(),o.options.scrollbarV&&o.getRows(),o.options.$outer.$digest(),s=!1}function r(){s||(Y(i),s=!0)}var s=!1,l=0,a=0,c=t.parent();o.options.internal.styleTranslator=new Z(o.options.rowHeight),o.options.internal.setYOffset=function(e){c[0].scrollTop=e},c.on("scroll",function(e){l=this.scrollTop,a=this.scrollLeft,r()}),e.$on("$destroy",function(){c.off("scroll")}),e.scrollerStyles=function(){return o.options.scrollbarV?{height:o.count*o.options.rowHeight+"px"}:void 0}}}}function g(e){return{restrict:"E",controller:_,controllerAs:"body",bindToController:{columns:"=",columnWidths:"=",rows:"=",options:"=",selected:"=?",expanded:"=?",onPage:"&",onTreeToggle:"&",onSelect:"&",onRowClick:"&",onRowDblClick:"&"},scope:!0,template:'\n \n \n
\n \n \n \n \n \n
\n
\n
\n
\n
'}}function f(e,t){return"single"===e?"asc"===t?"desc":"asc":t?"asc"===t?"desc":void 0:"asc"}function m(e){return{restrict:"E",controller:K,controllerAs:"hcell",scope:!0,bindToController:{options:"=",column:"=",onCheckboxChange:"&",onSort:"&",sortType:"=",onResize:"&",selected:"="},replace:!0,template:'',compile:function(){return{pre:function(t,n,o,i){var r=n[0].querySelector(".dt-header-cell-label"),s=void 0;if((i.column.headerTemplate||i.column.headerRenderer)&&(s=i.options.$outer.$new(!1),s.$header=i.column.name,s.$index=t.$index),i.column.headerTemplate){var l=angular.element(""+i.column.headerTemplate.trim()+" ");angular.element(r).append(e(l)(s))}else if(i.column.headerRenderer){var a=angular.element(i.column.headerRenderer(n));angular.element(r).append(e(a)(s)[0])}else{var c=i.column.name;void 0!==c&&null!==c||(c=""),r.textContent=c}}}}}}function v(e){return{restrict:"E",controller:J,controllerAs:"header",scope:!0,bindToController:{options:"=",columns:"=",columnWidths:"=",onSort:"&",onResize:"&",onCheckboxChange:"&"},template:'\n ',replace:!0,link:function(t,n,o,i){t.columnsResorted=function(t,n){var o=r(n),s=angular.element(t.currentTarget),l=-1;angular.forEach(s.children(),function(e,t){n===angular.element(e).attr("data-id")&&(l=t)}),e(function(){angular.forEach(i.columns,function(e){var t=e.indexOf(o);if(t>-1){var n=e[l],r=i.options.columns.indexOf(n),s=i.options.columns.indexOf(o);return i.options.columns.splice(s,1),i.options.columns.splice(r,0,o),!1}})})};var r=function(e){var t=i.columns.left.concat(i.columns.center).concat(i.columns.right);return t.find(function(t){return t.$id===e})}}}}function w(e){return{restrict:"A",scope:{isSortable:"=sortable",onSortableSort:"&"},link:function(e,t,n){function o(e,t){if(e.parentNode==t.parentNode)for(var n=e;n;n=n.previousSibling)if(n===t)return!0;return!1}function i(e){var t=e.target;o(l,t)?t.parentNode.insertBefore(l,t):t.nextSibling&&t.hasAttribute("draggable")&&t.parentNode.insertBefore(l,t.nextSibling.nextSibling)}function r(n){n.preventDefault(),l.classList.remove("dt-clone"),t.off("dragend",r),t.off("dragenter",i),a!==l.nextSibling&&e.onSortableSort({event:n,columnId:angular.element(l).attr("data-id")})}function s(n){return e.isSortable?(n=n.originalEvent||n,l=n.target,a=l.nextSibling,l.classList.add("dt-clone"),n.dataTransfer.effectAllowed="move",n.dataTransfer.setData("Text",l.textContent),t.on("dragenter",i),void t.on("dragend",r)):!1}var l,a;t[0];t.on("dragstart",s),e.$on("$destroy",function(){t.off("dragstart",s)})}}}function y(e,t){return{restrict:"A",scope:{isResizable:"=resizable",minWidth:"=",maxWidth:"=",onResize:"&"},link:function(n,o,i){function r(e){e=e.originalEvent||e;var t=c[0].clientWidth,o=e.movementX||e.mozMovementX||e.screenX-l,i=t+(o||0);l=e.screenX,(!n.minWidth||i>=n.minWidth)&&(!n.maxWidth||i<=n.maxWidth)&&c.css({width:i+"px"})}function s(){n.onResize&&t(function(){var e=c[0].clientWidth;e'),c=o.parent();a.on("mousedown",function(t){return o[0].classList.contains("resizable")?(t.stopPropagation(),t.preventDefault(),e.on("mousemove",r),void e.on("mouseup",s)):!1}),o.append(a)}}}function b(e,t,n){var o,i,r,s=null,l=0;n||(n={});var a=function(){l=n.leading===!1?0:new Date,s=null,r=e.apply(o,i)};return function(){var c=new Date;l||n.leading!==!1||(l=c);var d=t-(c-l);return o=this,i=arguments,0>=d?(clearTimeout(s),s=null,l=c,r=e.apply(o,i)):s||n.trailing===!1||(s=setTimeout(a,d)),r}}function C(){var e=document.createElement("div");e.style.visibility="hidden",e.style.width="100px",e.style.msOverflowStyle="scrollbar",document.body.appendChild(e);var t=e.offsetWidth;e.style.overflow="scroll";var n=document.createElement("div");n.style.width="100%",e.appendChild(n);var o=n.offsetWidth;return e.parentNode.removeChild(e),t-o}function x(){var e=((new Date).getTime()/1e3|0).toString(16);return e+"xxxxxxxxxxxxxxxx".replace(/[x]/g,function(){return(16*Math.random()|0).toString(16)}).toLowerCase()}function k(e,t,n){angular.forEach(e,function(e){e.forEach(function(e){e.canAutoResize?e.width=0:(t-=e.width,n-=e.flexGrow)})});var o={},i=t,r=function(){var t=i/n;i=0,angular.forEach(e,function(e){e.forEach(function(e,n){if(e.canAutoResize&&!o[n]){var r=e.width+e.flexGrow*t;void 0!==e.minWidth&&rn;n++){var i=e[n];i.frozenLeft?t.left.push(i):i.frozenRight?t.right.push(i):t.center.push(i)}return t}function R(e){var t=0,n=!0,o=!1,i=void 0;try{for(var r,s=e[Symbol.iterator]();!(n=(r=s.next()).done);n=!0){var l=r.value;t+=l.flexGrow||0}}catch(a){o=!0,i=a}finally{try{!n&&s["return"]&&s["return"]()}finally{if(o)throw i}}return t}function T(e,t){var n=0;return e.forEach(function(e){var o=t&&e[t];n+=o?e[t]:e.width}),n}function P(e,t){var n=T(e),o=R(e),i=$(e);n!==t&&k(i,t,o)}function S(e,t,n){var o=0,i=n>-1?e.slice(n,e.length).filter(function(e){return e.canAutoResize}):e.filter(function(e){return e.canAutoResize});e.forEach(function(e){o+=e.canAutoResize?e.$$oldWidth||e.width:e.width});var r=t-o,s=r/i.length,l=o>t;i.forEach(function(e){if(l)e.width=e.$$oldWidth||e.width;else{e.$$oldWidth||(e.$$oldWidth=e.width);var t=e.$$oldWidth+s;e.minWith&&te.maxWidth?e.width=e.maxWidth:e.width=t}})}function z(e,t){return{left:T(e.left),center:T(e.center),right:T(e.right),total:T(t)}}function W(e,t,n){return{restrict:"E",replace:!0,controller:ne,scope:!0,bindToController:{options:"=",rows:"=",selected:"=?",expanded:"=?",onSelect:"&",onSort:"&",onTreeToggle:"&",onPage:"&",onRowClick:"&",onRowDblClick:"&",onColumnResize:"&"},controllerAs:"dt",template:function(e){var t=e[0].getElementsByTagName("column"),n=x();return Q.saveColumns(n,t),'\n \n \n \n \n \n \n
'},compile:function(o,i){return{pre:function(o,i,r,s){function l(){var e=i[0].getBoundingClientRect();if(s.options.internal.innerWidth=Math.floor(e.width),s.options.scrollbarV){var t=e.height;s.options.headerHeight&&(t-=s.options.headerHeight),s.options.footerHeight&&(t-=s.options.footerHeight),s.options.internal.bodyHeight=t,s.calculatePageSize()}s.adjustColumns()}Q.buildColumns(o,n);var a=i.attr("data-column-id"),c=Q.columns[a];c&&(s.options.columns=c),s.transposeColumnDefaults(),s.options.internal.scrollBarWidth=C(),e.addEventListener("resize",b(function(){t(l)}));var d=function u(){var e=i[0].getBoundingClientRect(),n=e.width&&e.height;n?l():t(u,100)};d(),i.addClass("dt-loaded"),o.$on("$destroy",function(){angular.element(e).off("resize")})}}}}}W.$inject=["$window","$timeout","$parse"],y.$inject=["$document","$timeout"],w.$inject=["$timeout"],v.$inject=["$timeout"],m.$inject=["$compile"],g.$inject=["$timeout"],p.$inject=["$timeout","$rootScope"],r.$inject=["$rootScope","$compile","$log","$timeout"],Object.defineProperty(e,"__esModule",{value:!0});var E=function(){function e(e,t){for(var n=0;nn;n++)if(i(this[n],n,this)===!0)return"find"===e?this[n]:n;return"find"!==e?-1:void 0})}for(var t in{find:1,findIndex:1})e(t)}();var A=function(){function e(t){var o=this;n(this,e),t.$watch("pager.count",function(e){o.calcTotalPages(o.size,o.count),o.getPages(o.page||1)}),t.$watch("pager.size",function(e){o.calcTotalPages(o.size,o.count),o.getPages(o.page||1)}),t.$watch("pager.page",function(e){0!==e&&e<=o.totalPages&&o.getPages(e)}),this.getPages(this.page||1)}return e.$inject=["$scope"],E(e,[{key:"calcTotalPages",value:function(e,t){var t=1>e?1:Math.ceil(t/e);this.totalPages=Math.max(t||0,1)}},{key:"selectPage",value:function(e){e>0&&e<=this.totalPages&&(this.page=e,this.onPage({page:e}))}},{key:"prevPage",value:function(){this.page>1&&this.selectPage(--this.page)}},{key:"nextPage",value:function(){this.selectPage(++this.page)}},{key:"canPrevious",value:function(){return this.page>1}},{key:"canNext",value:function(){return this.page=s;s++)t.push({number:s,text:s,active:s===e});this.pages=t}}]),e}(),B=function(){function e(t){var o=this;n(this,e),this.page=this.paging.offset+1,t.$watch("footer.paging.offset",function(e){o.offsetChanged(e)})}return e.$inject=["$scope"],E(e,[{key:"offsetChanged",value:function(e){this.page=e+1}},{key:"onPaged",value:function(e){this.paging.offset=e-1,this.onPage({offset:this.paging.offset,size:this.paging.size})}}]),e}(),G=function(){function e(){n(this,e)}return E(e,[{key:"styles",value:function(){return{width:this.column.width+"px","min-width":this.column.width+"px"}}},{key:"cellClass",value:function(){var e={"dt-tree-col":this.column.isTreeColumn};return this.column.className&&(e[this.column.className]=!0),e}},{key:"treeClass",value:function(){return{"dt-tree-toggle":!0,"icon-right":!this.expanded,"icon-down":this.expanded}}},{key:"onTreeToggled",value:function(e){e.stopPropagation(),this.expanded=!this.expanded,this.onTreeToggle({cell:{value:this.value,column:this.column,expanded:this.expanded}})}},{key:"onCheckboxChanged",value:function(e){e.stopPropagation(),this.onCheckboxChange({$event:e})}},{key:"getValue",value:function(){var e=this.column.cellDataGetter?this.column.cellDataGetter(this.value):this.value;return void 0!==e&&null!==e||(e=""),e}}]),e}(),D={},H=document.createElement("div").style,M=function(){var e=window.getComputedStyle(document.documentElement,""),t=(Array.prototype.slice.call(e).join("").match(/-(moz|webkit|ms)-/)||""===e.OLink&&["","o"])[1],n="WebKit|Moz|MS|O".match(new RegExp("("+t+")","i"))[1];return{dom:n,lowercase:t,css:"-"+t+"-",js:t[0].toUpperCase()+t.substr(1)}}(),N=l("transform"),O=l("backfaceVisibility"),V=!!l("transform"),j=!!l("perspective"),L=window.navigator.userAgent,I=/Safari\//.test(L)&&!/Chrome\//.test(L),F=function(){function e(){n(this,e)}return E(e,[{key:"onGroupToggled",value:function(e){e.stopPropagation(),this.onGroupToggle({group:this.row})}},{key:"treeClass",value:function(){return{"dt-tree-toggle":!0,"icon-right":!this.expanded,"icon-down":this.expanded}}}]),e}(),U=function(){function e(){n(this,e)}return E(e,[{key:"getValue",value:function(e){return e.prop?d(this.row,e.prop):""}},{key:"onTreeToggled",value:function(e){this.onTreeToggle({cell:e,row:this.row})}},{key:"stylesByGroup",value:function(e){var t={width:this.columnWidths[e]+"px"};if("left"===e)a(t,this.options.internal.offsetX,0);else if("right"===e){var n=-1*(this.columnWidths.total-this.options.internal.innerWidth-this.options.internal.offsetX+this.options.internal.scrollBarWidth);a(t,n,0)}return t}},{key:"onCheckboxChanged",value:function(e){this.onCheckboxChange({$event:e,row:this.row})}}]),e}(),X={BACKSPACE:8,TAB:9,RETURN:13,ALT:18,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,DELETE:46,COMMA:188,PERIOD:190,A:65,Z:90,ZERO:48,NUMPAD_0:96,NUMPAD_9:105},q=function(){function e(t){n(this,e),this.body=t.body,this.options=t.body.options,this.selected=t.body.selected}return e.$inject=["$scope"],E(e,[{key:"keyDown",value:function(e,t,n){if(X[e.keyCode]&&e.preventDefault(),e.keyCode===X.DOWN){var o=e.target.nextElementSibling;o&&o.focus()}else if(e.keyCode===X.UP){var i=e.target.previousElementSibling;i&&i.focus()}else e.keyCode===X.RETURN&&this.selectRow(t,n)}},{key:"rowClicked",value:function(e,t,n){this.options.checkboxSelection||this.selectRow(e,t,n),this.body.onRowClick({row:n})}},{key:"rowDblClicked",value:function(e,t,n){this.options.checkboxSelection||(e.preventDefault(),this.selectRow(e,t,n)),this.body.onRowDblClick({row:n})}},{key:"onCheckboxChange",value:function(e,t,n){this.selectRow(e,t,n)}},{key:"selectRow",value:function(e,t,n){if(this.options.selectable)if(this.options.multiSelect){var o=(e.ctrlKey||e.metaKey,e.shiftKey);if(o)this.selectRowsBetween(t,n);else{var i=this.selected.indexOf(n);i>-1?this.selected.splice(i,1):(this.options.multiSelectOnShift&&1===this.selected.length&&this.selected.splice(0,1),this.selected.push(n),this.body.onSelect({rows:[n]}))}this.prevIndex=t}else this.selected=n,this.body.onSelect({rows:[n]})}},{key:"selectRowsBetween",value:function(e){for(var t=eo;o++){var r=this.body.rows[o],s=o>=this.prevIndex&&e>=o,l=o<=this.prevIndex&&o>=e,a={};if(a=t?{start:e,end:this.prevIndex-e}:{start:this.prevIndex,end:e+1},t&&l||!t&&s){var c=this.selected.indexOf(r);if(t&&c>-1){this.selected.splice(c,1);continue}o>=a.start&&ot)&&(i.getRows(),r=!0)}),t.$watch("body.options.paging.count",function(e){i.count=e,i.updatePage()}),t.$watch("body.options.paging.offset",function(e){i.options.paging.size&&i.onPage({offset:e,size:i.options.paging.size})})}}return e.$inject=["$scope","$timeout"],E(e,[{key:"rowsUpdated",value:function(e,n){if(e)if(this.options.paging.externalPaging||(this.options.paging.count=e.length),this.count=this.options.paging.count,(this.treeColumn||this.groupColumn)&&this.buildRowsByGroup(),this.options.scrollbarV){var o=e&&n&&(e.length===n.length||e.lengtho?Math.floor(o):o>n?Math.ceil(o):e,isNaN(o)||(this.options.paging.offset=o)}},{key:"calculateDepth",value:function(e){var t=arguments.length<=1||void 0===arguments[1]?0:arguments[1],n=this.treeColumn?this.treeColumn.relationProp:this.groupColumn.prop,o=this.treeColumn.prop;if(!e[n])return t;if(e.$$depth)return e.$$depth+t;var i=this.index[e[n]];if(i)return t+=1,this.calculateDepth(i,t);for(var r=0,s=this.rows.length;s>r;r++){var l=this.rows[r];if(l[o]==e[n])return t+=1,this.calculateDepth(l,t)}return t}},{key:"buildRowsByGroup",value:function(){this.index={},this.rowsByGroup={};for(var e=this.treeColumn?this.treeColumn.relationProp:this.groupColumn.prop,t=0,n=this.rows.length;n>t;t++){var o=this.rows[t],i=o[e];if(i&&(this.rowsByGroup[i]?this.rowsByGroup[i].push(o):this.rowsByGroup[i]=[o]),this.treeColumn){var r=this.treeColumn.prop;if(this.index[o[r]]=o,void 0===o[e])o.$$depth=0;else{var s=this.index[o[e]];if(void 0===s)for(var l=0;n>l;l++)if(this.rows[l][r]==i){s=this.rows[l];
-break}void 0===s.$$depth&&(s.$$depth=this.calculateDepth(s)),o.$$depth=s.$$depth+1,s.$$children?s.$$children.push(o[r]):s.$$children=[o[r]]}}}}},{key:"buildGroups",value:function(){var e=this,n=[];return angular.forEach(this.rowsByGroup,function(o,i){n.push({name:i,group:!0}),e.expanded[i]&&n.push.apply(n,t(o))}),n}},{key:"isSelected",value:function(e){var t=!1;return this.options.selectable&&(t=this.options.multiSelect?this.selected.indexOf(e)>-1:this.selected===e),t}},{key:"buildTree",value:function(){function e(t,o,i){t.forEach(function(t){var r=t[n.treeColumn.relationProp],s=t[n.treeColumn.prop],l=n.rowsByGroup[s],a=n.expanded[s];(i>0||!r)&&(o.push(t),l&&l.length>0&&a&&e(l,o,i+1))})}var t=[],n=this;return e(this.rows,t,0),t}},{key:"getRows",value:function(e){if((this.treeColumn||this.groupColumn)&&!this.rowsByGroup)return!1;var t;this.treeColumn?(t=this.treeTemp||[],!e&&this.treeTemp||(this.treeTemp=t=this.buildTree(),this.count=t.length,this.tempRows.splice(0,this.tempRows.length))):this.groupColumn?(t=this.groupsTemp||[],!e&&this.groupsTemp||(this.groupsTemp=t=this.buildGroups(),this.count=t.length)):(t=this.rows,e===!0&&this.tempRows.splice(0,this.tempRows.length));var n=0,o=this.getFirstLastIndexes(),i=o.first;for(this.tempRows.splice(0,o.last-o.first);ie;e++){var n=this.options.columns[e];n.$id=x(),angular.forEach(ee,function(e,t){n.hasOwnProperty(t)||(n[t]=e)}),n.name&&!n.prop&&(n.prop=s(n.name)),this.options.columns[e]=n}}},{key:"calculateColumns",value:function(){var e=this.options.columns;this.columnsByPin=$(e),this.columnWidths=z(this.columnsByPin,e)}},{key:"tableCss",value:function(){return{fixed:this.options.scrollbarV,selectable:this.options.selectable,checkboxable:this.options.checkboxSelection}}},{key:"adjustColumns",value:function(e){var t=this.options.internal.innerWidth-this.options.internal.scrollBarWidth;"force"===this.options.columnMode?S(this.options.columns,t,e):"flex"===this.options.columnMode&&P(this.options.columns,t)}},{key:"calculatePageSize",value:function(){this.options.paging.size=Math.ceil(this.options.internal.bodyHeight/this.options.rowHeight)+1}},{key:"onSorted",value:function(){if(this.rows){var e=this.options.columns.filter(function(e){return e.sort}).sort(function(e,t){if(e.sortPriority&&t.sortPriority){if(e.sortPriority>t.sortPriority)return 1;if(e.sortPriorityo;o++){var r=e[o];if(r.comparator!==!1){var s="asc"===r.sort?"":"-";void 0!==r.sortBy?n.push(s+r.sortBy):n.push(s+r.prop)}}if(n.length){var l,a=this.$filter("orderBy")(this.rows,n);this.rows.splice(0,this.rows.length),(l=this.rows).push.apply(l,t(a))}}this.options.internal.setYOffset(0)}}},{key:"onTreeToggled",value:function(e,t){this.onTreeToggle({row:e,cell:t})}},{key:"onBodyPage",value:function(e,t){this.onPage({offset:e,size:t})}},{key:"onFooterPage",value:function(e,t){var n=this.options.rowHeight*t,o=n*e;this.options.internal.setYOffset(o)}},{key:"onHeaderCheckboxChange",value:function(){if(this.rows){var e=this.selected.length===this.rows.length;if(this.selected.splice(0,this.selected.length),!e){var n;(n=this.selected).push.apply(n,t(this.rows))}}}},{key:"isAllRowsSelected",value:function(){return this.rows?!1:this.selected.length===this.rows.length}},{key:"onResized",value:function(e,t){var n=this.options.columns.indexOf(e);if(n>-1){var e=this.options.columns[n];e.width=t,e.canAutoResize=!1,this.adjustColumns(n),this.calculateColumns()}this.onColumnResize&&this.onColumnResize({column:e,width:t})}},{key:"onSelected",value:function(e){this.onSelect({rows:e})}},{key:"onRowClicked",value:function(e){this.onRowClick({row:e})}},{key:"onRowDblClicked",value:function(e){this.onRowDblClick({row:e})}}]),e}(),oe=angular.module("data-table",[]).directive("dtable",W).directive("resizable",y).directive("sortable",w).directive("dtHeader",v).directive("dtHeaderCell",m).directive("dtBody",g).directive("dtScroller",p).directive("dtSeletion",h).directive("dtRow",u).directive("dtGroupRow",c).directive("dtCell",r).directive("dtFooter",i).directive("dtPager",o);e["default"]=oe});
\ No newline at end of file
+!function(e,t){if("function"==typeof define&&define.amd)define("DataTable",["exports","angular"],t);else if("undefined"!=typeof exports)t(exports,require("angular"));else{var n={exports:{}};t(n.exports,e.angular),e.DataTable=n.exports}}(this,function(e,t){"use strict";function n(e){return e&&e.__esModule?e:{default:e}}function o(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t=n.minWidth)&&(!n.maxWidth||i<=n.maxWidth)&&c.css({width:i+"px"})}function l(){n.onResize&&t(function(){var e=c[0].clientWidth;e'),c=o.parent();a.on("mousedown",function(t){return!!o[0].classList.contains("resizable")&&(t.stopPropagation(),t.preventDefault(),e.on("mousemove",r),void e.on("mouseup",l))}),o.append(a)}}}function l(e){return{restrict:"A",scope:{isSortable:"=sortable",onSortableSort:"&"},link:function(e,t,n){function o(e,t){if(e.parentNode==t.parentNode)for(var n=e;n;n=n.previousSibling)if(n===t)return!0;return!1}function i(e){var t=e.target;o(s,t)?t.parentNode.insertBefore(s,t):t.nextSibling&&t.hasAttribute("draggable")&&t.parentNode.insertBefore(s,t.nextSibling.nextSibling)}function r(n){n.preventDefault(),s.classList.remove("dt-clone"),t.off("dragend",r),t.off("dragenter",i),a!==s.nextSibling&&e.onSortableSort({event:n,columnId:N.default.element(s).attr("data-id")})}function l(n){return!!e.isSortable&&(n=n.originalEvent||n,s=n.target,a=s.nextSibling,s.classList.add("dt-clone"),n.dataTransfer.effectAllowed="move",n.dataTransfer.setData("Text",s.textContent),t.on("dragenter",i),void t.on("dragend",r))}var s,a;t[0];t.on("dragstart",l),e.$on("$destroy",function(){t.off("dragstart",l)})}}}function s(){var e=((new Date).getTime()/1e3|0).toString(16);return e+"xxxxxxxxxxxxxxxx".replace(/[x]/g,function(){return(16*Math.random()|0).toString(16)}).toLowerCase()}function a(e){for(var t={left:[],center:[],right:[]},n=0,o=e.length;n-1?e.slice(n,e.length).filter(function(e){return e.canAutoResize}):e.filter(function(e){return e.canAutoResize});e.forEach(function(e){o+=e.canAutoResize?e.$$oldWidth||e.width:e.width});var r=t-o,l=r/i.length,s=o>t;i.forEach(function(e){if(s)e.width=e.$$oldWidth||e.width;else{e.$$oldWidth||(e.$$oldWidth=e.width);var t=e.$$oldWidth+l;e.minWith&&te.maxWidth?e.width=e.maxWidth:e.width=t}})}function y(e,t,n){var o,i,r,l=null,s=0;n||(n={});var a=function(){s=n.leading===!1?0:new Date,l=null,r=e.apply(o,i)};return function(){var c=new Date;s||n.leading!==!1||(s=c);var d=t-(c-s);return o=this,i=arguments,d<=0?(clearTimeout(l),l=null,s=c,r=e.apply(o,i)):l||n.trailing===!1||(l=setTimeout(a,d)),r}}function b(e,t,n){return{restrict:"E",replace:!0,controller:U,scope:!0,bindToController:{options:"=",rows:"=",selected:"=?",expanded:"=?",onSelect:"&",onSort:"&",onTreeToggle:"&",onPage:"&",onRowClick:"&",onRowDblClick:"&",onColumnResize:"&"},controllerAs:"dt",template:function(e){var t=e[0].getElementsByTagName("column"),n=s();return X.saveColumns(n,t),'\n \n \n \n \n \n \n
'},compile:function(o,i){return{pre:function(o,i,r,l){function s(){var e=i[0].getBoundingClientRect();if(l.options.internal.innerWidth=Math.floor(e.width),l.options.scrollbarV){var t=e.height;l.options.headerHeight&&(t-=l.options.headerHeight),l.options.footerHeight&&(t-=l.options.footerHeight),l.options.internal.bodyHeight=t,l.calculatePageSize()}l.adjustColumns()}X.buildColumns(o,n);var a=i.attr("data-column-id"),c=X.columns[a];c&&(l.options.columns=c),l.transposeColumnDefaults(),l.options.internal.scrollBarWidth=h(),e.addEventListener("resize",y(function(){t(s)}));var d=function e(){var n=i[0].getBoundingClientRect(),o=n.width&&n.height;o?s():t(e,100)};d(),i.addClass("dt-loaded"),o.$on("$destroy",function(){N.default.element(e).off("resize")})}}}}}function C(e){var t=u(e);return j[t]||(void 0!==_[K.css+e]?j[t]=K.css+e:void 0!==_[e]&&(j[t]=e)),j[t]}function x(e,t,n){J?!te&&Q?(e[Y]="translate3d("+t+"px, "+n+"px, 0)",e[Z]="hidden"):e[u(Y)]="translate("+t+"px, "+n+"px)":(e.top=n+"px",e.left=t+"px")}function k(e){return{restrict:"E",controller:ne,controllerAs:"header",scope:!0,bindToController:{options:"=",columns:"=",columnWidths:"=",onSort:"&",onResize:"&",onCheckboxChange:"&"},template:'\n ',replace:!0,link:function(t,n,o,i){t.columnsResorted=function(t,n){var o=r(n),l=N.default.element(t.currentTarget),s=-1;N.default.forEach(l.children(),function(e,t){n===N.default.element(e).attr("data-id")&&(s=t)}),e(function(){N.default.forEach(i.columns,function(e){var t=e.indexOf(o);if(t>-1){var n=e[s],r=i.options.columns.indexOf(n),l=i.options.columns.indexOf(o);return i.options.columns.splice(l,1),i.options.columns.splice(r,0,o),!1}})})};var r=function(e){var t=i.columns.left.concat(i.columns.center).concat(i.columns.right);return t.find(function(t){return t.$id===e})}}}}function $(e){return{restrict:"E",controller:oe,controllerAs:"hcell",scope:!0,bindToController:{options:"=",column:"=",onCheckboxChange:"&",onSort:"&",sortType:"=",onResize:"&",selected:"="},replace:!0,template:'',compile:function(){return{pre:function(t,n,o,i){var r=n[0].querySelector(".dt-header-cell-label"),l=void 0;if((i.column.headerTemplate||i.column.headerRenderer)&&(l=i.options.$outer.$new(!1),l.$header=i.column.name,l.$index=t.$index),i.column.headerTemplate){var s=N.default.element(""+i.column.headerTemplate.trim()+" ");N.default.element(r).append(e(s)(l))}else if(i.column.headerRenderer){var a=N.default.element(i.column.headerRenderer(n));N.default.element(r).append(e(a)(l)[0])}else{var c=i.column.name;void 0!==c&&null!==c||(c=""),r.textContent=c}}}}}}function R(e){return{restrict:"E",controller:ie,controllerAs:"body",bindToController:{columns:"=",columnWidths:"=",rows:"=",options:"=",selected:"=?",expanded:"=?",onPage:"&",onTreeToggle:"&",onSelect:"&",onRowClick:"&",onRowDblClick:"&"},scope:!0,template:'\n \n \n
\n \n \n \n \n \n
\n
\n
\n
\n
'}}function T(e,t){return{restrict:"E",require:"^dtBody",transclude:!0,replace:!0,template:'
',link:function(e,t,n,o){function i(){o.options.internal.offsetY=s,o.options.internal.offsetX=a,o.updatePage(),o.options.scrollbarV&&o.getRows(),o.options.$outer.$digest(),l=!1}function r(){l||(q(i),l=!0)}var l=!1,s=0,a=0,c=t.parent();o.options.internal.styleTranslator=new re(o.options.rowHeight),o.options.internal.setYOffset=function(e){c[0].scrollTop=e},c.on("scroll",function(e){s=this.scrollTop,a=this.scrollLeft,r()}),e.$on("$destroy",function(){c.off("scroll")}),e.scrollerStyles=function(){if(o.options.scrollbarV)return{height:o.count*o.options.rowHeight+"px"}}}}}function P(){return{controller:se,restrict:"A",require:"^dtBody",controllerAs:"selCtrl"}}function S(){return{restrict:"E",controller:ae,controllerAs:"rowCtrl",scope:!0,bindToController:{row:"=",columns:"=",columnWidths:"=",expanded:"=",selected:"=",hasChildren:"=",options:"=",onCheckboxChange:"&",onTreeToggle:"&"},link:function(e,t,n,o){o.row&&x(t[0].style,0,o.row.$$index*o.options.rowHeight),o.options.internal.styleTranslator.register(e.$index,t)},template:'\n \n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
',replace:!0}}function z(){return{restrict:"E",controller:ce,controllerAs:"group",bindToController:{row:"=",onGroupToggle:"&",expanded:"=",options:"="},scope:!0,replace:!0,template:'\n \n \n \n \n \n
',link:function(e,t,n,o){x(t[0].style,0,o.row.$$index*o.options.rowHeight),o.options.internal.styleTranslator.register(e.$index,t)}}}function E(e,t,n,o){return{restrict:"E",controller:de,scope:!0,controllerAs:"cell",bindToController:{options:"=",value:"=",selected:"=",column:"=",row:"=",expanded:"=",hasChildren:"=",onTreeToggle:"&",onCheckboxChange:"&"},template:'\n \n \n \n \n \n
',replace:!0,compile:function(){return{pre:function(e,n,o,i){function r(){l=i.options.$outer.$new(!1),l.getValue=i.getValue}var l,s=N.default.element(n[0].querySelector(".dt-cell-content"));(i.column.template||i.column.cellRenderer)&&r(),e.$watch("cell.row",function(){if(l&&(l.$destroy(),r(),l.$cell=i.value,l.$row=i.row,l.$column=i.column,l.$$watchers=null),i.column.template){s.empty();var e=N.default.element(""+i.column.template.trim()+" ");s.append(t(e)(l))}else if(i.column.cellRenderer){s.empty();var e=N.default.element(i.column.cellRenderer(l,s));s.append(t(e)(l))}else s[0].innerHTML=i.getValue()},!0)}}}}}function W(){return{restrict:"E",controller:ue,controllerAs:"footer",scope:!0,bindToController:{paging:"=",onPage:"&"},template:'',replace:!0}}function A(){return{restrict:"E",controller:he,controllerAs:"pager",scope:!0,bindToController:{page:"=",size:"=",count:"=",onPage:"&"},template:'',replace:!0}}function B(e,t,n,o,i,r,l){function s(e,t){return e?N.default.isString(e)&&t?e:n.get(e)||$http.get(e,{cache:!0}):""}function a(e){if(e&&0!==e.length){var t=(""+e).toLowerCase();e="true"==t}else e=!1;return e}return{restrict:"A",scope:!0,replace:!1,link:function(n,c,d){function u(){n.exitTimeout=t(p,500)}function h(){t.cancel(n.exitTimeout);var r=document.getElementById("#"+n.popoverId);n.popover&&r||(n.options.group&&i.removeGroup(n.options.group,n.popoverId),n.options.text&&!n.options.template?(n.popover=N.default.element('
'),n.popover.html(n.options.text),N.default.element(document.body).append(n.popover),g(c,n.popover,n.options),i.add(n.popoverId,{element:c,popover:n.popover,group:n.options.group})):e.when(s(n.options.template,n.options.plain)).then(function(e){N.default.isString(e)||(e=e.data&&N.default.isString(e.data)?e.data:""),n.popover=N.default.element('
'),n.popover.html(e),o(n.popover)(n),N.default.element(document.body).append(n.popover),g(c,n.popover,n.options),n.popover.off("mouseleave",u),n.popover.on("mouseleave",u),n.popover.on("mouseenter",function(){t.cancel(n.exitTimeout)}),i.add(n.popoverId,{element:c,popover:n.popover,group:n.options.group})}))}function p(){n.popover&&n.popover.remove(),n.popover=void 0,i.remove(n.popoverId)}function g(e,o,i){t(function(){var t,s,a=e[0].getBoundingClientRect(),c=o[0].getBoundingClientRect();"right"===i.placement&&(s=a.left+a.width+i.spacing,t=r.calculateVerticalAlignment(a,c,i.alignment)),"left"===i.placement&&(s=a.left-c.width-i.spacing,t=r.calculateVerticalAlignment(a,c,i.alignment)),"top"===i.placement&&(t=a.top-c.height-i.spacing,s=r.calculateHorizontalAlignment(a,c,i.alignment)),"bottom"===i.placement&&(t=a.top+a.height+i.spacing,s=r.calculateHorizontalAlignment(a,c,i.alignment)),o.css({top:t+"px",left:s+"px"}),n.options.showCaret&&f(n.popover,a,c),l.addClass(n.popover,"popover-animation")},50)}function f(e,t,o){var i=N.default.element(' ');e.append(i);var l,s,a=i[0].getBoundingClientRect();"right"===n.options.placement&&(l=-6,s=r.calculateVerticalCaret(t,o,a,n.options.alignment)),"left"===n.options.placement&&(l=o.width-2,s=r.calculateVerticalCaret(t,o,a,n.options.alignment)),"top"===n.options.placement&&(s=o.height-5,l=r.calculateHorizontalCaret(t,o,a,n.options.alignment)),"bottom"===n.options.placement&&(s=-8,l=r.calculateHorizontalCaret(t,o,a,n.options.alignment)),i.css({top:s+"px",left:l+"px"})}n.popover=null,n.popoverId=Date.now(),n.options={text:d.popoverText,template:d.popoverTemplate,plain:a(d.popoverPlain||!1),placement:d.popoverPlacement||"right",alignment:d.popoverAlignment||"center",group:d.popoverGroup,spacing:parseInt(d.popoverSpacing)||0,showCaret:a(d.popoverPlain||!1)},c.off("mouseenter",h),c.on("mouseenter",h),c.off("mouseleave",u),c.on("mouseleave",u)}}}function G(e){var t={};this.add=function(e,n){t[e]=n},this.find=function(e){t[e]},this.remove=function(e){delete t[e]},this.removeGroup=function(n,o){angular.forEach(t,function(i,r){r!==o&&i.group&&i.group===n&&e.removeClass(i.popover,"sw-popover-animate").then(function(){i.popover.remove(),delete t[r]})})}}function D(){return{calculateVerticalAlignment:function(e,t,n){return"top"===n?e.top:"bottom"===n?e.top+e.height-t.height:"center"===n?e.top+e.height/2-t.height/2:void 0},calculateVerticalCaret:function(e,t,n,o){return"top"===o?e.height/2-n.height/2-1:"bottom"===o?t.height-e.height/2-n.height/2-1:"center"===o?t.height/2-n.height/2-1:void 0},calculateHorizontalCaret:function(e,t,n,o){return"left"===o?e.width/2-n.height/2-1:"right"===o?t.width-e.width/2-n.height/2-1:"center"===o?t.width/2-n.height/2-1:void 0},calculateHorizontalAlignment:function(e,t,n){return"left"===n?e.left:"right"===n?e.left+e.width-t.width:"center"===n?e.left+e.width/2-t.width/2:void 0}}}function H(){return{restrict:"E",controller:"MenuController",controllerAs:"dtm",scope:{current:"=",available:"="},template:''}}function M(e,t){return{restrict:"C",controller:"DropdownController",link:function(n,o,i){function r(e){o[0].contains(e.target)||t(function(){n.open=!1,s()})}function l(e){27===e.which&&t(function(){n.open=!1,s()})}function s(){e.unbind("click",r),e.unbind("keydown",l)}n.$watch("open",function(t){t&&(e.bind("click",r),e.bind("keydown",l))})}}}function I(e){return{restrict:"C",controller:"DropdownController",require:"?^dropdown",link:function(t,n,o,i){function r(n){n.preventDefault(),e(function(){i.toggle(t)})}function l(){n.unbind("click",r)}n.bind("click",r),t.$on("$destroy",l)}}}function V(e){return{restrict:"C",require:"?^dropdown",link:function(t,n,o,i){t.$watch("open",function(){e[t.open?"addClass":"removeClass"](n,"ddm-open")})}}}Object.defineProperty(e,"__esModule",{value:!0}),e.dtMenu=e.dtPopover=void 0;var N=n(t),O=function(){function e(e,t){for(var n=0;nt.sortPriority)return 1;if(e.sortPriority-1){var e=this.options.columns[n];e.width=t,e.canAutoResize=!1,this.adjustColumns(n),this.calculateColumns()}this.onColumnResize&&this.onColumnResize({column:e,width:t})}},{key:"onSelected",value:function(e){this.onSelect({rows:e})}},{key:"onRowClicked",value:function(e){this.onRowClick({row:e})}},{key:"onRowDblClicked",value:function(e){this.onRowDblClick({row:e})}}]),e}(),X={columns:{},dTables:{},saveColumns:function(e,t){if(t&&t.length){var n=[].slice.call(t);this.dTables[e]=n}},buildColumns:function(e,t){var n=this;N.default.forEach(this.dTables,function(o,i){n.columns[i]=[],N.default.forEach(o,function(o){var r={},l=!0;N.default.forEach(o.attributes,function(n){var o=u(n.name);switch(o){case"class":r.className=n.value;break;case"name":case"prop":r[o]=n.value;break;case"headerRenderer":case"cellRenderer":case"cellDataGetter":r[o]=t(n.value);break;case"visible":l=t(n.value)(e);break;default:r[o]=t(n.value)(e)}});var s=o.getElementsByTagName("column-header");s.length&&(r.headerTemplate=s[0].innerHTML,o.removeChild(s[0])),""!==o.innerHTML&&(r.template=o.innerHTML),l&&n.columns[i].push(r)})}),this.dTables={}}},j={},_=document.createElement("div").style,K=function(){var e=window.getComputedStyle(document.documentElement,""),t=(Array.prototype.slice.call(e).join("").match(/-(moz|webkit|ms)-/)||""===e.OLink&&["","o"])[1],n="WebKit|Moz|MS|O".match(new RegExp("("+t+")","i"))[1];return{dom:n,lowercase:t,css:"-"+t+"-",js:t[0].toUpperCase()+t.substr(1)}}(),Y=C("transform"),Z=C("backfaceVisibility"),J=!!C("transform"),Q=!!C("perspective"),ee=window.navigator.userAgent,te=/Safari\//.test(ee)&&!/Chrome\//.test(ee),ne=function(){function e(){i(this,e)}return O(e,[{key:"styles",value:function(){return{width:this.options.internal.innerWidth+"px",height:this.options.headerHeight+"px"}}},{key:"innerStyles",value:function(){return{width:this.columnWidths.total+"px"}}},{key:"onSorted",value:function(e){if("single"===this.options.sortType){var t=function(t){t!==e&&(t.sort=void 0)};this.columns.left.forEach(t),this.columns.center.forEach(t),this.columns.right.forEach(t)}this.onSort({column:e})}},{key:"stylesByGroup",value:function(e){var t={width:this.columnWidths[e]+"px"};if("center"===e)x(t,this.options.internal.offsetX*-1,0);else if("right"===e){var n=(this.columnWidths.total-this.options.internal.innerWidth)*-1;x(t,n,0)}return t}},{key:"onCheckboxChanged",value:function(){this.onCheckboxChange()}},{key:"onResized",value:function(e,t){this.onResize({column:e,width:t})}}]),e}(),oe=function(){function e(){i(this,e)}return O(e,[{key:"styles",value:function(){return{width:this.column.width+"px",minWidth:this.column.minWidth+"px",maxWidth:this.column.maxWidth+"px",height:this.column.height+"px"}}},{key:"cellClass",value:function(){var e={sortable:this.column.sortable,resizable:this.column.resizable};return this.column.headerClassName&&(e[this.column.headerClassName]=!0),e}},{key:"onSorted",value:function(){this.column.sortable&&(this.column.sort=p(this.sortType,this.column.sort),void 0===this.column.sort&&(this.column.sortPriority=void 0),this.onSort({column:this.column}))}},{key:"sortClass",value:function(){return{"sort-btn":!0,"sort-asc icon-down":"asc"===this.column.sort,"sort-desc icon-up":"desc"===this.column.sort}}},{key:"onResized",value:function(e,t){this.onResize({column:t,width:e})}},{key:"onCheckboxChange",value:function(){this.onCheckboxChanged()}}]),e}(),ie=function(){function e(t,n){var o=this;if(i(this,e),this.$scope=t,this.tempRows=[],this.treeColumn=this.options.columns.find(function(e){return e.isTreeColumn}),this.groupColumn=this.options.columns.find(function(e){return e.group}),t.$watchCollection("body.rows",this.rowsUpdated.bind(this)),this.options.scrollbarV||!this.options.scrollbarV&&this.options.paging.externalPaging){var r=!1;t.$watch("body.options.paging.size",function(e,t){(!r||e>t)&&(o.getRows(),r=!0)}),t.$watch("body.options.paging.count",function(e){o.count=e,o.updatePage()}),t.$watch("body.options.paging.offset",function(e){o.options.paging.size&&o.onPage({offset:e,size:o.options.paging.size})})}}return O(e,[{key:"rowsUpdated",value:function(e,t){if(e)if(this.options.paging.externalPaging||(this.options.paging.count=e.length),this.count=this.options.paging.count,(this.treeColumn||this.groupColumn)&&this.buildRowsByGroup(),this.options.scrollbarV){var n=e&&t&&(e.length===t.length||e.lengthn?Math.ceil(o):e,isNaN(o)||(this.options.paging.offset=o)}},{key:"calculateDepth",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=this.treeColumn?this.treeColumn.relationProp:this.groupColumn.prop,o=this.treeColumn.prop;if(!e[n])return t;if(e.$$depth)return e.$$depth+t;var i=this.index[e[n]];if(i)return t+=1,this.calculateDepth(i,t);for(var r=0,l=this.rows.length;r-1:this.selected===e),t}},{key:"buildTree",value:function(){function e(t,o,i){t.forEach(function(t){var r=t[n.treeColumn.relationProp],l=t[n.treeColumn.prop],s=n.rowsByGroup[l],a=n.expanded[l];(i>0||!r)&&(o.push(t),s&&s.length>0&&a&&e(s,o,i+1))})}var t=[],n=this;return e(this.rows,t,0),t}},{key:"getRows",value:function(e){if((this.treeColumn||this.groupColumn)&&!this.rowsByGroup)return!1;var t;this.treeColumn?(t=this.treeTemp||[],!e&&this.treeTemp||(this.treeTemp=t=this.buildTree(),this.count=t.length,this.tempRows.splice(0,this.tempRows.length))):this.groupColumn?(t=this.groupsTemp||[],!e&&this.groupsTemp||(this.groupsTemp=t=this.buildGroups(),this.count=t.length)):(t=this.rows,e===!0&&this.tempRows.splice(0,this.tempRows.length));var n=0,o=this.getFirstLastIndexes(),i=o.first;for(this.tempRows.splice(0,o.last-o.first);i-1?this.selected.splice(i,1):(this.options.multiSelectOnShift&&1===this.selected.length&&this.selected.splice(0,1),this.selected.push(n),this.body.onSelect({rows:[n]}))}this.prevIndex=t}else this.selected=n,this.body.onSelect({rows:[n]})}},{key:"selectRowsBetween",value:function(e){for(var t=e=this.prevIndex&&o<=e,s=o<=this.prevIndex&&o>=e,a={};if(a=t?{start:e,end:this.prevIndex-e}:{start:this.prevIndex,end:e+1},t&&s||!t&&l){var c=this.selected.indexOf(r);if(t&&c>-1){this.selected.splice(c,1);continue}o>=a.start&&o0&&e<=this.totalPages&&(this.page=e,this.onPage({page:e}))}},{key:"prevPage",value:function(){this.page>1&&this.selectPage(--this.page)}},{key:"nextPage",value:function(){this.selectPage(++this.page)}},{key:"canPrevious",value:function(){return this.page>1}},{key:"canNext",value:function(){return this.page-1}},{key:"onCheck",value:function(e){var t=this.getColumnIndex(e);t===-1?this.$scope.current.push(e):this.$scope.current.splice(t,1)}}]),e}(),fe=function(){function e(t){i(this,e),t.open=!1}return O(e,[{key:"toggle",value:function(e){e.open=!e.open}}]),e}(),me=N.default.module("dt.dropdown",[]).controller("DropdownController",fe).directive("dropdown",M).directive("dropdownToggle",I).directive("dropdownMenu",V),ve=N.default.module("dt.menu",[me.name]).controller("MenuController",ge).directive("dtm",H),we=N.default.module("data-table",[]).directive("dtable",b).directive("resizable",r).directive("sortable",l).directive("dtHeader",k).directive("dtHeaderCell",$).directive("dtBody",R).directive("dtScroller",T).directive("dtSeletion",P).directive("dtRow",S).directive("dtGroupRow",z).directive("dtCell",E).directive("dtFooter",W).directive("dtPager",A);e.dtPopover=pe,e.dtMenu=ve,e.default=we});
\ No newline at end of file
diff --git a/src/components/popover/popover.js b/src/components/popover/popover.js
index 6e72d76..f576fc4 100644
--- a/src/components/popover/popover.js
+++ b/src/components/popover/popover.js
@@ -4,7 +4,7 @@ import { PopoverRegistry } from './PopoverRegistry';
import { PositionHelper } from './PositionHelper';
export default angular
- .module('popover', [])
+ .module('dt.popover', [])
.service('PopoverRegistry', PopoverRegistry)
.factory('PositionHelper', PositionHelper)
.directive('popover', PopoverDirective);
diff --git a/src/dataTable.js b/src/dataTable.js
index bc559d0..43c4acc 100644
--- a/src/dataTable.js
+++ b/src/dataTable.js
@@ -15,6 +15,10 @@ import { GroupRowDirective } from './components/body/GroupRowDirective';
import { CellDirective } from './components/body/CellDirective';
import { FooterDirective } from './components/footer/FooterDirective';
import { PagerDirective } from './components/footer/PagerDirective';
+import dtPopover from './components/popover/popover';
+import dtMenu from './components/menu/menu';
+
+export { dtPopover, dtMenu };
export default angular
.module('data-table', [])
diff --git a/src/dataTable.less b/src/dataTable.less
index 399cc8f..65deb17 100644
--- a/src/dataTable.less
+++ b/src/dataTable.less
@@ -1,4 +1,6 @@
.dt{
+ @import "./components/popover/popover.less";
+ @import "./components/menu/menu.less";
visibility: hidden;
overflow:hidden;
@@ -195,4 +197,3 @@
}
}
}
-