UNPKG

contractus

Version:

Software de Gerenciamento de Contratos Lumenit

1,398 lines (1,178 loc) 949 kB
/*! * ui-grid - v3.0.0-rc.22 - 2015-06-15 * Copyright (c) 2015 ; License: MIT */ (function () { 'use strict'; angular.module('ui.grid.i18n', []); angular.module('ui.grid', ['ui.grid.i18n']); })(); (function () { 'use strict'; angular.module('ui.grid').constant('uiGridConstants', { LOG_DEBUG_MESSAGES: true, LOG_WARN_MESSAGES: true, LOG_ERROR_MESSAGES: true, CUSTOM_FILTERS: /CUSTOM_FILTERS/g, COL_FIELD: /COL_FIELD/g, MODEL_COL_FIELD: /MODEL_COL_FIELD/g, TOOLTIP: /title=\"TOOLTIP\"/g, DISPLAY_CELL_TEMPLATE: /DISPLAY_CELL_TEMPLATE/g, TEMPLATE_REGEXP: /<.+>/, FUNC_REGEXP: /(\([^)]*\))?$/, DOT_REGEXP: /\./g, APOS_REGEXP: /'/g, BRACKET_REGEXP: /^(.*)((?:\s*\[\s*\d+\s*\]\s*)|(?:\s*\[\s*"(?:[^"\\]|\\.)*"\s*\]\s*)|(?:\s*\[\s*'(?:[^'\\]|\\.)*'\s*\]\s*))(.*)$/, COL_CLASS_PREFIX: 'ui-grid-col', events: { GRID_SCROLL: 'uiGridScroll', COLUMN_MENU_SHOWN: 'uiGridColMenuShown', ITEM_DRAGGING: 'uiGridItemDragStart', // For any item being dragged COLUMN_HEADER_CLICK: 'uiGridColumnHeaderClick' }, // copied from http://www.lsauer.com/2011/08/javascript-keymap-keycodes-in-json.html keymap: { TAB: 9, STRG: 17, CAPSLOCK: 20, CTRL: 17, CTRLRIGHT: 18, CTRLR: 18, SHIFT: 16, RETURN: 13, ENTER: 13, BACKSPACE: 8, BCKSP: 8, ALT: 18, ALTR: 17, ALTRIGHT: 17, SPACE: 32, WIN: 91, MAC: 91, FN: null, PG_UP: 33, PG_DOWN: 34, UP: 38, DOWN: 40, LEFT: 37, RIGHT: 39, ESC: 27, DEL: 46, F1: 112, F2: 113, F3: 114, F4: 115, F5: 116, F6: 117, F7: 118, F8: 119, F9: 120, F10: 121, F11: 122, F12: 123 }, ASC: 'asc', DESC: 'desc', filter: { STARTS_WITH: 2, ENDS_WITH: 4, EXACT: 8, CONTAINS: 16, GREATER_THAN: 32, GREATER_THAN_OR_EQUAL: 64, LESS_THAN: 128, LESS_THAN_OR_EQUAL: 256, NOT_EQUAL: 512, SELECT: 'select', INPUT: 'input' }, aggregationTypes: { sum: 2, count: 4, avg: 8, min: 16, max: 32 }, // TODO(c0bra): Create full list of these somehow. NOTE: do any allow a space before or after them? CURRENCY_SYMBOLS: ['ƒ', '$', '£', '$', '¤', '¥', '៛', '₩', '₱', '฿', '₫'], scrollDirection: { UP: 'up', DOWN: 'down', LEFT: 'left', RIGHT: 'right', NONE: 'none' }, dataChange: { ALL: 'all', EDIT: 'edit', ROW: 'row', COLUMN: 'column', OPTIONS: 'options' }, scrollbars: { NEVER: 0, ALWAYS: 1 //WHEN_NEEDED: 2 } }); })(); angular.module('ui.grid').directive('uiGridCell', ['$compile', '$parse', 'gridUtil', 'uiGridConstants', function ($compile, $parse, gridUtil, uiGridConstants) { var uiGridCell = { priority: 0, scope: false, require: '?^uiGrid', compile: function() { return { pre: function($scope, $elm, $attrs, uiGridCtrl) { function compileTemplate() { var compiledElementFn = $scope.col.compiledElementFn; compiledElementFn($scope, function(clonedElement, scope) { $elm.append(clonedElement); }); } // If the grid controller is present, use it to get the compiled cell template function if (uiGridCtrl && $scope.col.compiledElementFn) { compileTemplate(); } // No controller, compile the element manually (for unit tests) else { if ( uiGridCtrl && !$scope.col.compiledElementFn ){ // gridUtil.logError('Render has been called before precompile. Please log a ui-grid issue'); $scope.col.getCompiledElementFn() .then(function (compiledElementFn) { compiledElementFn($scope, function(clonedElement, scope) { $elm.append(clonedElement); }); }); } else { var html = $scope.col.cellTemplate .replace(uiGridConstants.MODEL_COL_FIELD, 'row.entity.' + gridUtil.preEval($scope.col.field)) .replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)'); var cellElement = $compile(html)($scope); $elm.append(cellElement); } } }, post: function($scope, $elm, $attrs, uiGridCtrl) { var initColClass = $scope.col.getColClass(false); $elm.addClass(initColClass); var classAdded; var updateClass = function( grid ){ var contents = $elm; if ( classAdded ){ contents.removeClass( classAdded ); classAdded = null; } if (angular.isFunction($scope.col.cellClass)) { classAdded = $scope.col.cellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex); } else { classAdded = $scope.col.cellClass; } contents.addClass(classAdded); }; if ($scope.col.cellClass) { updateClass(); } // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN, uiGridConstants.dataChange.EDIT]); // watch the col and row to see if they change - which would indicate that we've scrolled or sorted or otherwise // changed the row/col that this cell relates to, and we need to re-evaluate cell classes and maybe other things var cellChangeFunction = function( n, o ){ if ( n !== o ) { if ( classAdded || $scope.col.cellClass ){ updateClass(); } // See if the column's internal class has changed var newColClass = $scope.col.getColClass(false); if (newColClass !== initColClass) { $elm.removeClass(initColClass); $elm.addClass(newColClass); initColClass = newColClass; } } }; // TODO(c0bra): Turn this into a deep array watch /* shouldn't be needed any more given track by col.name var colWatchDereg = $scope.$watch( 'col', cellChangeFunction ); */ var rowWatchDereg = $scope.$watch( 'row', cellChangeFunction ); var deregisterFunction = function() { dataChangeDereg(); // colWatchDereg(); rowWatchDereg(); }; $scope.$on( '$destroy', deregisterFunction ); $elm.on( '$destroy', deregisterFunction ); } }; } }; return uiGridCell; }]); (function(){ angular.module('ui.grid') .service('uiGridColumnMenuService', [ 'i18nService', 'uiGridConstants', 'gridUtil', function ( i18nService, uiGridConstants, gridUtil ) { /** * @ngdoc service * @name ui.grid.service:uiGridColumnMenuService * * @description Services for working with column menus, factored out * to make the code easier to understand */ var service = { /** * @ngdoc method * @methodOf ui.grid.service:uiGridColumnMenuService * @name initialize * @description Sets defaults, puts a reference to the $scope on * the uiGridController * @param {$scope} $scope the $scope from the uiGridColumnMenu * @param {controller} uiGridCtrl the uiGridController for the grid * we're on * */ initialize: function( $scope, uiGridCtrl ){ $scope.grid = uiGridCtrl.grid; // Store a reference to this link/controller in the main uiGrid controller // to allow showMenu later uiGridCtrl.columnMenuScope = $scope; // Save whether we're shown or not so the columns can check $scope.menuShown = false; }, /** * @ngdoc method * @methodOf ui.grid.service:uiGridColumnMenuService * @name setColMenuItemWatch * @description Setup a watch on $scope.col.menuItems, and update * menuItems based on this. $scope.col needs to be set by the column * before calling the menu. * @param {$scope} $scope the $scope from the uiGridColumnMenu * @param {controller} uiGridCtrl the uiGridController for the grid * we're on * */ setColMenuItemWatch: function ( $scope ){ var deregFunction = $scope.$watch('col.menuItems', function (n, o) { if (typeof(n) !== 'undefined' && n && angular.isArray(n)) { n.forEach(function (item) { if (typeof(item.context) === 'undefined' || !item.context) { item.context = {}; } item.context.col = $scope.col; }); $scope.menuItems = $scope.defaultMenuItems.concat(n); } else { $scope.menuItems = $scope.defaultMenuItems; } }); $scope.$on( '$destroy', deregFunction ); }, /** * @ngdoc boolean * @name enableSorting * @propertyOf ui.grid.class:GridOptions.columnDef * @description (optional) True by default. When enabled, this setting adds sort * widgets to the column header, allowing sorting of the data in the individual column. */ /** * @ngdoc method * @methodOf ui.grid.service:uiGridColumnMenuService * @name sortable * @description determines whether this column is sortable * @param {$scope} $scope the $scope from the uiGridColumnMenu * */ sortable: function( $scope ) { if ( $scope.grid.options.enableSorting && typeof($scope.col) !== 'undefined' && $scope.col && $scope.col.enableSorting) { return true; } else { return false; } }, /** * @ngdoc method * @methodOf ui.grid.service:uiGridColumnMenuService * @name isActiveSort * @description determines whether the requested sort direction is current active, to * allow highlighting in the menu * @param {$scope} $scope the $scope from the uiGridColumnMenu * @param {string} direction the direction that we'd have selected for us to be active * */ isActiveSort: function( $scope, direction ){ return (typeof($scope.col) !== 'undefined' && typeof($scope.col.sort) !== 'undefined' && typeof($scope.col.sort.direction) !== 'undefined' && $scope.col.sort.direction === direction); }, /** * @ngdoc method * @methodOf ui.grid.service:uiGridColumnMenuService * @name suppressRemoveSort * @description determines whether we should suppress the removeSort option * @param {$scope} $scope the $scope from the uiGridColumnMenu * */ suppressRemoveSort: function( $scope ) { if ($scope.col && $scope.col.suppressRemoveSort) { return true; } else { return false; } }, /** * @ngdoc boolean * @name enableHiding * @propertyOf ui.grid.class:GridOptions.columnDef * @description (optional) True by default. When set to false, this setting prevents a user from hiding the column * using the column menu or the grid menu. */ /** * @ngdoc method * @methodOf ui.grid.service:uiGridColumnMenuService * @name hideable * @description determines whether a column can be hidden, by checking the enableHiding columnDef option * @param {$scope} $scope the $scope from the uiGridColumnMenu * */ hideable: function( $scope ) { if (typeof($scope.col) !== 'undefined' && $scope.col && $scope.col.colDef && $scope.col.colDef.enableHiding === false ) { return false; } else { return true; } }, /** * @ngdoc method * @methodOf ui.grid.service:uiGridColumnMenuService * @name getDefaultMenuItems * @description returns the default menu items for a column menu * @param {$scope} $scope the $scope from the uiGridColumnMenu * */ getDefaultMenuItems: function( $scope ){ return [ { title: i18nService.getSafeText('sort.ascending'), icon: 'ui-grid-icon-sort-alt-up', action: function($event) { $event.stopPropagation(); $scope.sortColumn($event, uiGridConstants.ASC); }, shown: function () { return service.sortable( $scope ); }, active: function() { return service.isActiveSort( $scope, uiGridConstants.ASC); } }, { title: i18nService.getSafeText('sort.descending'), icon: 'ui-grid-icon-sort-alt-down', action: function($event) { $event.stopPropagation(); $scope.sortColumn($event, uiGridConstants.DESC); }, shown: function() { return service.sortable( $scope ); }, active: function() { return service.isActiveSort( $scope, uiGridConstants.DESC); } }, { title: i18nService.getSafeText('sort.remove'), icon: 'ui-grid-icon-cancel', action: function ($event) { $event.stopPropagation(); $scope.unsortColumn(); }, shown: function() { return service.sortable( $scope ) && typeof($scope.col) !== 'undefined' && (typeof($scope.col.sort) !== 'undefined' && typeof($scope.col.sort.direction) !== 'undefined') && $scope.col.sort.direction !== null && !service.suppressRemoveSort( $scope ); } }, { title: i18nService.getSafeText('column.hide'), icon: 'ui-grid-icon-cancel', shown: function() { return service.hideable( $scope ); }, action: function ($event) { $event.stopPropagation(); $scope.hideColumn(); } } ]; }, /** * @ngdoc method * @methodOf ui.grid.service:uiGridColumnMenuService * @name getColumnElementPosition * @description gets the position information needed to place the column * menu below the column header * @param {$scope} $scope the $scope from the uiGridColumnMenu * @param {GridCol} column the column we want to position below * @param {element} $columnElement the column element we want to position below * @returns {hash} containing left, top, offset, height, width * */ getColumnElementPosition: function( $scope, column, $columnElement ){ var positionData = {}; positionData.left = $columnElement[0].offsetLeft; positionData.top = $columnElement[0].offsetTop; positionData.parentLeft = $columnElement[0].offsetParent.offsetLeft; // Get the grid scrollLeft positionData.offset = 0; if (column.grid.options.offsetLeft) { positionData.offset = column.grid.options.offsetLeft; } positionData.height = gridUtil.elementHeight($columnElement, true); positionData.width = gridUtil.elementWidth($columnElement, true); return positionData; }, /** * @ngdoc method * @methodOf ui.grid.service:uiGridColumnMenuService * @name repositionMenu * @description Reposition the menu below the new column. If the menu has no child nodes * (i.e. it's not currently visible) then we guess it's width at 100, we'll be called again * later to fix it * @param {$scope} $scope the $scope from the uiGridColumnMenu * @param {GridCol} column the column we want to position below * @param {hash} positionData a hash containing left, top, offset, height, width * @param {element} $elm the column menu element that we want to reposition * @param {element} $columnElement the column element that we want to reposition underneath * */ repositionMenu: function( $scope, column, positionData, $elm, $columnElement ) { var menu = $elm[0].querySelectorAll('.ui-grid-menu'); var containerId = column.renderContainer ? column.renderContainer : 'body'; var renderContainer = column.grid.renderContainers[containerId]; // It's possible that the render container of the column we're attaching to is // offset from the grid (i.e. pinned containers), we need to get the difference in the offsetLeft // between the render container and the grid var renderContainerElm = gridUtil.closestElm($columnElement, '.ui-grid-render-container'); var renderContainerOffset = renderContainerElm.getBoundingClientRect().left - $scope.grid.element[0].getBoundingClientRect().left; var containerScrollLeft = renderContainerElm.querySelectorAll('.ui-grid-viewport')[0].scrollLeft; // default value the last width for _this_ column, otherwise last width for _any_ column, otherwise default to 170 var myWidth = column.lastMenuWidth ? column.lastMenuWidth : ( $scope.lastMenuWidth ? $scope.lastMenuWidth : 170); var paddingRight = column.lastMenuPaddingRight ? column.lastMenuPaddingRight : ( $scope.lastMenuPaddingRight ? $scope.lastMenuPaddingRight : 10); if ( menu.length !== 0 ){ var mid = menu[0].querySelectorAll('.ui-grid-menu-mid'); if ( mid.length !== 0 && !angular.element(mid).hasClass('ng-hide') ) { myWidth = gridUtil.elementWidth(menu, true); $scope.lastMenuWidth = myWidth; column.lastMenuWidth = myWidth; // TODO(c0bra): use padding-left/padding-right based on document direction (ltr/rtl), place menu on proper side // Get the column menu right padding paddingRight = parseInt(gridUtil.getStyles(angular.element(menu)[0])['paddingRight'], 10); $scope.lastMenuPaddingRight = paddingRight; column.lastMenuPaddingRight = paddingRight; } } var left = positionData.left + renderContainerOffset - containerScrollLeft + positionData.parentLeft + positionData.width - myWidth + paddingRight; if (left < positionData.offset){ left = positionData.offset; } $elm.css('left', left + 'px'); $elm.css('top', (positionData.top + positionData.height) + 'px'); } }; return service; }]) .directive('uiGridColumnMenu', ['$timeout', 'gridUtil', 'uiGridConstants', 'uiGridColumnMenuService', function ($timeout, gridUtil, uiGridConstants, uiGridColumnMenuService) { /** * @ngdoc directive * @name ui.grid.directive:uiGridColumnMenu * @description Provides the column menu framework, leverages uiGridMenu underneath * */ var uiGridColumnMenu = { priority: 0, scope: true, require: '?^uiGrid', templateUrl: 'ui-grid/uiGridColumnMenu', replace: true, link: function ($scope, $elm, $attrs, uiGridCtrl) { var self = this; uiGridColumnMenuService.initialize( $scope, uiGridCtrl ); $scope.defaultMenuItems = uiGridColumnMenuService.getDefaultMenuItems( $scope ); // Set the menu items for use with the column menu. The user can later add additional items via the watch $scope.menuItems = $scope.defaultMenuItems; uiGridColumnMenuService.setColMenuItemWatch( $scope ); /** * @ngdoc method * @methodOf ui.grid.directive:uiGridColumnMenu * @name showMenu * @description Shows the column menu. If the menu is already displayed it * calls the menu to ask it to hide (it will animate), then it repositions the menu * to the right place whilst hidden (it will make an assumption on menu width), * then it asks the menu to show (it will animate), then it repositions the menu again * once we can calculate it's size. * @param {GridCol} column the column we want to position below * @param {element} $columnElement the column element we want to position below */ $scope.showMenu = function(column, $columnElement, event) { // Swap to this column $scope.col = column; // Get the position information for the column element var colElementPosition = uiGridColumnMenuService.getColumnElementPosition( $scope, column, $columnElement ); if ($scope.menuShown) { // we want to hide, then reposition, then show, but we want to wait for animations // we set a variable, and then rely on the menu-hidden event to call the reposition and show $scope.colElement = $columnElement; $scope.colElementPosition = colElementPosition; $scope.hideThenShow = true; $scope.$broadcast('hide-menu', { originalEvent: event }); } else { self.shown = $scope.menuShown = true; uiGridColumnMenuService.repositionMenu( $scope, column, colElementPosition, $elm, $columnElement ); $scope.colElement = $columnElement; $scope.colElementPosition = colElementPosition; $scope.$broadcast('show-menu', { originalEvent: event }); } }; /** * @ngdoc method * @methodOf ui.grid.directive:uiGridColumnMenu * @name hideMenu * @description Hides the column menu. * @param {boolean} broadcastTrigger true if we were triggered by a broadcast * from the menu itself - in which case don't broadcast again as we'll get * an infinite loop */ $scope.hideMenu = function( broadcastTrigger ) { // delete $scope.col; $scope.menuShown = false; if ( !broadcastTrigger ){ $scope.$broadcast('hide-menu'); } }; $scope.$on('menu-hidden', function() { if ( $scope.hideThenShow ){ delete $scope.hideThenShow; uiGridColumnMenuService.repositionMenu( $scope, $scope.col, $scope.colElementPosition, $elm, $scope.colElement ); $scope.$broadcast('show-menu'); $scope.menuShown = true; } else { $scope.hideMenu( true ); } }); $scope.$on('menu-shown', function() { $timeout( function() { uiGridColumnMenuService.repositionMenu( $scope, $scope.col, $scope.colElementPosition, $elm, $scope.colElement ); delete $scope.colElementPosition; delete $scope.columnElement; }, 200); }); /* Column methods */ $scope.sortColumn = function (event, dir) { event.stopPropagation(); $scope.grid.sortColumn($scope.col, dir, true) .then(function () { $scope.grid.refresh(); $scope.hideMenu(); }); }; $scope.unsortColumn = function () { $scope.col.unsort(); $scope.grid.refresh(); $scope.hideMenu(); }; $scope.hideColumn = function () { $scope.col.colDef.visible = false; $scope.col.visible = false; $scope.grid.queueGridRefresh(); $scope.hideMenu(); $scope.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN ); $scope.grid.api.core.raise.columnVisibilityChanged( $scope.col ); }; }, controller: ['$scope', function ($scope) { var self = this; $scope.$watch('menuItems', function (n, o) { self.menuItems = n; }); }] }; return uiGridColumnMenu; }]); })(); (function(){ 'use strict'; angular.module('ui.grid').directive('uiGridFilter', ['$compile', '$templateCache', function ($compile, $templateCache) { return { compile: function() { return { pre: function ($scope, $elm, $attrs, controllers) { $scope.col.updateFilters = function( filterable ){ $elm.children().remove(); if ( filterable ){ var template = $scope.col.filterHeaderTemplate; $elm.append($compile(template)($scope)); } }; $scope.$on( '$destroy', function() { delete $scope.col.updateFilters; }); } }; } }; }]); })(); (function () { 'use strict'; angular.module('ui.grid').directive('uiGridFooterCell', ['$timeout', 'gridUtil', 'uiGridConstants', '$compile', function ($timeout, gridUtil, uiGridConstants, $compile) { var uiGridFooterCell = { priority: 0, scope: { col: '=', row: '=', renderIndex: '=' }, replace: true, require: '^uiGrid', compile: function compile(tElement, tAttrs, transclude) { return { pre: function ($scope, $elm, $attrs, uiGridCtrl) { var cellFooter = $compile($scope.col.footerCellTemplate)($scope); $elm.append(cellFooter); }, post: function ($scope, $elm, $attrs, uiGridCtrl) { //$elm.addClass($scope.col.getColClass(false)); $scope.grid = uiGridCtrl.grid; var initColClass = $scope.col.getColClass(false); $elm.addClass(initColClass); // apply any footerCellClass var classAdded; var updateClass = function( grid ){ var contents = $elm; if ( classAdded ){ contents.removeClass( classAdded ); classAdded = null; } if (angular.isFunction($scope.col.footerCellClass)) { classAdded = $scope.col.footerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex); } else { classAdded = $scope.col.footerCellClass; } contents.addClass(classAdded); }; if ($scope.col.footerCellClass) { updateClass(); } $scope.col.updateAggregationValue(); // Watch for column changes so we can alter the col cell class properly /* shouldn't be needed any more, given track by col.name $scope.$watch('col', function (n, o) { if (n !== o) { // See if the column's internal class has changed var newColClass = $scope.col.getColClass(false); if (newColClass !== initColClass) { $elm.removeClass(initColClass); $elm.addClass(newColClass); initColClass = newColClass; } } }); */ // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN]); // listen for visible rows change and update aggregation values $scope.grid.api.core.on.rowsRendered( $scope, $scope.col.updateAggregationValue ); $scope.$on( '$destroy', dataChangeDereg ); } }; } }; return uiGridFooterCell; }]); })(); (function () { 'use strict'; angular.module('ui.grid').directive('uiGridFooter', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', function ($templateCache, $compile, uiGridConstants, gridUtil, $timeout) { return { restrict: 'EA', replace: true, // priority: 1000, require: ['^uiGrid', '^uiGridRenderContainer'], scope: true, compile: function ($elm, $attrs) { return { pre: function ($scope, $elm, $attrs, controllers) { var uiGridCtrl = controllers[0]; var containerCtrl = controllers[1]; $scope.grid = uiGridCtrl.grid; $scope.colContainer = containerCtrl.colContainer; containerCtrl.footer = $elm; var footerTemplate = $scope.grid.options.footerTemplate; gridUtil.getTemplate(footerTemplate) .then(function (contents) { var template = angular.element(contents); var newElm = $compile(template)($scope); $elm.append(newElm); if (containerCtrl) { // Inject a reference to the footer viewport (if it exists) into the grid controller for use in the horizontal scroll handler below var footerViewport = $elm[0].getElementsByClassName('ui-grid-footer-viewport')[0]; if (footerViewport) { containerCtrl.footerViewport = footerViewport; } } }); }, post: function ($scope, $elm, $attrs, controllers) { var uiGridCtrl = controllers[0]; var containerCtrl = controllers[1]; // gridUtil.logDebug('ui-grid-footer link'); var grid = uiGridCtrl.grid; // Don't animate footer cells gridUtil.disableAnimations($elm); containerCtrl.footer = $elm; var footerViewport = $elm[0].getElementsByClassName('ui-grid-footer-viewport')[0]; if (footerViewport) { containerCtrl.footerViewport = footerViewport; } } }; } }; }]); })(); (function () { 'use strict'; angular.module('ui.grid').directive('uiGridGridFooter', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', function ($templateCache, $compile, uiGridConstants, gridUtil, $timeout) { return { restrict: 'EA', replace: true, // priority: 1000, require: '^uiGrid', scope: true, compile: function ($elm, $attrs) { return { pre: function ($scope, $elm, $attrs, uiGridCtrl) { $scope.grid = uiGridCtrl.grid; var footerTemplate = $scope.grid.options.gridFooterTemplate; gridUtil.getTemplate(footerTemplate) .then(function (contents) { var template = angular.element(contents); var newElm = $compile(template)($scope); $elm.append(newElm); }); }, post: function ($scope, $elm, $attrs, controllers) { } }; } }; }]); })(); (function(){ 'use strict'; angular.module('ui.grid').directive('uiGridGroupPanel', ["$compile", "uiGridConstants", "gridUtil", function($compile, uiGridConstants, gridUtil) { var defaultTemplate = 'ui-grid/ui-grid-group-panel'; return { restrict: 'EA', replace: true, require: '?^uiGrid', scope: false, compile: function($elm, $attrs) { return { pre: function ($scope, $elm, $attrs, uiGridCtrl) { var groupPanelTemplate = $scope.grid.options.groupPanelTemplate || defaultTemplate; gridUtil.getTemplate(groupPanelTemplate) .then(function (contents) { var template = angular.element(contents); var newElm = $compile(template)($scope); $elm.append(newElm); }); }, post: function ($scope, $elm, $attrs, uiGridCtrl) { $elm.bind('$destroy', function() { // scrollUnbinder(); }); } }; } }; }]); })(); (function(){ 'use strict'; angular.module('ui.grid').directive('uiGridHeaderCell', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'ScrollEvent', function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, ScrollEvent) { // Do stuff after mouse has been down this many ms on the header cell var mousedownTimeout = 500; var changeModeTimeout = 500; // length of time between a touch event and a mouse event being recognised again, and vice versa var uiGridHeaderCell = { priority: 0, scope: { col: '=', row: '=', renderIndex: '=' }, require: ['?^uiGrid', '^uiGridRenderContainer'], replace: true, compile: function() { return { pre: function ($scope, $elm, $attrs) { var cellHeader = $compile($scope.col.headerCellTemplate)($scope); $elm.append(cellHeader); }, post: function ($scope, $elm, $attrs, controllers) { var uiGridCtrl = controllers[0]; var renderContainerCtrl = controllers[1]; $scope.grid = uiGridCtrl.grid; $scope.renderContainer = uiGridCtrl.grid.renderContainers[renderContainerCtrl.containerId]; var initColClass = $scope.col.getColClass(false); $elm.addClass(initColClass); // Hide the menu by default $scope.menuShown = false; // Put asc and desc sort directions in scope $scope.asc = uiGridConstants.ASC; $scope.desc = uiGridConstants.DESC; // Store a reference to menu element var $colMenu = angular.element( $elm[0].querySelectorAll('.ui-grid-header-cell-menu') ); var $contentsElm = angular.element( $elm[0].querySelectorAll('.ui-grid-cell-contents') ); // apply any headerCellClass var classAdded; var previousMouseX; // filter watchers var filterDeregisters = []; /* * Our basic approach here for event handlers is that we listen for a down event (mousedown or touchstart). * Once we have a down event, we need to work out whether we have a click, a drag, or a * hold. A click would sort the grid (if sortable). A drag would be used by moveable, so * we ignore it. A hold would open the menu. * * So, on down event, we put in place handlers for move and up events, and a timer. If the * timer expires before we see a move or up, then we have a long press and hence a column menu open. * If the up happens before the timer, then we have a click, and we sort if the column is sortable. * If a move happens before the timer, then we are doing column move, so we do nothing, the moveable feature * will handle it. * * To deal with touch enabled devices that also have mice, we only create our handlers when * we get the down event, and we create the corresponding handlers - if we're touchstart then * we get touchmove and touchend, if we're mousedown then we get mousemove and mouseup. * * We also suppress the click action whilst this is happening - otherwise after the mouseup there * will be a click event and that can cause the column menu to close * */ $scope.downFn = function( event ){ event.stopPropagation(); if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) { event = event.originalEvent; } // Don't show the menu if it's not the left button if (event.button && event.button !== 0) { return; } previousMouseX = event.pageX; $scope.mousedownStartTime = (new Date()).getTime(); $scope.mousedownTimeout = $timeout(function() { }, mousedownTimeout); $scope.mousedownTimeout.then(function () { if ( $scope.colMenu ) { uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm, event); } }); uiGridCtrl.fireEvent(uiGridConstants.events.COLUMN_HEADER_CLICK, {event: event, columnName: $scope.col.colDef.name}); $scope.offAllEvents(); if ( event.type === 'touchstart'){ $document.on('touchend', $scope.upFn); $document.on('touchmove', $scope.moveFn); } else if ( event.type === 'mousedown' ){ $document.on('mouseup', $scope.upFn); $document.on('mousemove', $scope.moveFn); } }; $scope.upFn = function( event ){ event.stopPropagation(); $timeout.cancel($scope.mousedownTimeout); $scope.offAllEvents(); $scope.onDownEvents(event.type); var mousedownEndTime = (new Date()).getTime(); var mousedownTime = mousedownEndTime - $scope.mousedownStartTime; if (mousedownTime > mousedownTimeout) { // long click, handled above with mousedown } else { // short click if ( $scope.sortable ){ $scope.handleClick(event); } } }; $scope.moveFn = function( event ){ // Chrome is known to fire some bogus move events. var changeValue = event.pageX - previousMouseX; if ( changeValue === 0 ){ return; } // we're a move, so do nothing and leave for column move (if enabled) to take over $timeout.cancel($scope.mousedownTimeout); $scope.offAllEvents(); $scope.onDownEvents(event.type); }; $scope.clickFn = function ( event ){ event.stopPropagation(); $contentsElm.off('click', $scope.clickFn); }; $scope.offAllEvents = function(){ $contentsElm.off('touchstart', $scope.downFn); $contentsElm.off('mousedown', $scope.downFn); $document.off('touchend', $scope.upFn); $document.off('mouseup', $scope.upFn); $document.off('touchmove', $scope.moveFn); $document.off('mousemove', $scope.moveFn); $contentsElm.off('click', $scope.clickFn); }; $scope.onDownEvents = function( type ){ // If there is a previous event, then wait a while before // activating the other mode - i.e. if the last event was a touch event then // don't enable mouse events for a wee while (500ms or so) // Avoids problems with devices that emulate mouse events when you have touch events switch (type){ case 'touchmove': case 'touchend': $contentsElm.on('click', $scope.clickFn); $contentsElm.on('touchstart', $scope.downFn); $timeout(function(){ $contentsElm.on('mousedown', $scope.downFn); }, changeModeTimeout); break; case 'mousemove': case 'mouseup': $contentsElm.on('click', $scope.clickFn); $contentsElm.on('mousedown', $scope.downFn); $timeout(function(){ $contentsElm.on('touchstart', $scope.downFn); }, changeModeTimeout); break; default: $contentsElm.on('click', $scope.clickFn); $contentsElm.on('touchstart', $scope.downFn); $contentsElm.on('mousedown', $scope.downFn); } }; var updateHeaderOptions = function( grid ){ var contents = $elm; if ( classAdded ){ contents.removeClass( classAdded ); classAdded = null; } if (angular.isFunction($scope.col.headerCellClass)) { classAdded = $scope.col.headerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex); } else { classAdded = $scope.col.headerCellClass; } contents.addClass(classAdded); var rightMostContainer = $scope.grid.renderContainers['right'] ? $scope.grid.renderContainers['right'] : $scope.grid.renderContainers['body']; $scope.isLastCol = ( $scope.col === rightMostContainer.visibleColumnCache[ rightMostContainer.visibleColumnCache.length - 1 ] ); // Figure out whether this column is sortable or not if (uiGridCtrl.grid.options.enableSorting && $scope.col.enableSorting) { $scope.sortable = true; } else { $scope.sortable = false; } // Figure out whether this column is filterable or not var oldFilterable = $scope.filterable; if (uiGridCtrl.grid.options.enableFiltering && $scope.col.enableFiltering) { $scope.filterable = true; } else { $scope.filterable = false; } if ( oldFilterable !== $scope.filterable){ if ( typeof($scope.col.updateFilters) !== 'undefined' ){ $scope.col.updateFilters($scope.filterable); } // if column is filterable add a filter watcher if ($scope.filterable) { $scope.col.filters.forEach( function(filter, i) { filterDeregisters.push($scope.$watch('col.filters[' + i + '].term', function(n, o) { if (n !== o) { uiGridCtrl.grid.api.core.raise.filterChanged(); uiGridCtrl.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN ); uiGridCtrl.grid.queueGridRefresh(); } })); }); $scope.$on('$destroy', function() { filterDeregisters.forEach( function(filterDeregister) { filterDeregister(); }); }); } else { filterDeregisters.forEach( function(filterDeregister) { filterDeregister(); }); } } // figure out whether we support column menus if ($scope.col.grid.options && $scope.col.grid.options.enableColumnMenus !== false && $scope.col.colDef && $scope.col.colDef.enableColumnMenu !== false){ $scope.colMenu = true; } else { $scope.colMenu = false; } /** * @ngdoc property * @name enableColumnMenu * @propertyOf ui.grid.class:GridOptions.columnDef * @description if column menus are enabled, controls the column menus for this specific * column (i.e. if gridOptions.enableColumnMenus, then you can control column menus * using this option. If gridOptions.enableColumnMenus === false then you get no column * menus irrespective of the value of this option ). Defaults to true. * */ /** * @ngdoc property * @name enableColumnMenus * @propertyOf ui.grid.class:GridOptions.columnDef * @description Override for column menus everywhere - if set to false then you get no * column menus. Defaults to true. * */ $scope.offAllEvents(); if ($scope.sortable || $scope.colMenu) { $scope.onDownEvents(); $scope.$on('$destroy', function () { $scope.offAllEvents(); }); } }; /* $scope.$watch('col', function (n, o) { if (n !== o) { // See if the column's internal class has changed var newColClass = $scope.col.getColClass(false); if (newColClass !== initColClass) { $elm.removeClass(initColClass); $elm.addClass(newColClass); initColClass = newColClass; } } }); */ updateHeaderOptions(); // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateHeaderOptions, [uiGridConstants.dataChange.COLUMN]); $scope.$on( '$destroy', dataChangeDereg ); $scope.handleClick = function(event) { // If the shift key is being held down, add this column to the sort var add = false; if (event.shiftKey) { add = true; } // Sort this column then rebuild the grid's rows uiGridCtrl.grid.sortColumn($scope.col, add) .then(function () { if (uiGridCtrl.columnMenuScope) { uiGridCtrl.columnMenuScope.hideMenu(); } uiGridCtrl.grid.refresh(); }); }; $scope.toggleMenu = function(event) { event.stopPropagation(); // If the menu is already showing... if (uiGridCtrl.columnMenuScope.menuShown) { // ... and we're the column the menu is on... if (uiGridCtrl.columnMenuScope.col === $scope.col) { // ... hide it uiGridCtrl.columnMenuScope.hideMenu(); } // ... and we're NOT the column the menu is on else { // ... move the menu to our column uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm); } } // If the menu is NOT showing else { // ... show it on our column uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm); } }; } }; } }; return uiGridHeaderCell; }]); })(); (function(){ 'use strict'; angular.module('ui.grid').directive('uiGridHeader', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', 'ScrollEvent', function($templateCache, $compile, uiGridConstants, gridUtil, $timeout, ScrollEvent) { var defaultTemplate = 'ui-grid/ui-grid-header'; var emptyTemplate = 'ui-grid/ui-grid-no-header'; return { restrict: 'EA', // templateUrl: 'ui-grid/ui-grid-header', replace: true, // priority: 1000, require: ['^uiGrid', '^uiGridRenderContainer'], scope: true, compile: function($elm, $attrs) { return { pre: function ($scope, $elm, $attrs, controllers) { var uiGridCtrl = controllers[0]; var containerCtrl = controllers[1]; $scope.grid = uiGridCtrl.grid; $scope.colContainer = containerCtrl.colContainer; updateHeaderReferences(); var headerTemplate; if (!$scope.grid.options.showHeader) { headerTemplate = emptyTemplate; } else { headerTemplate = ($scope.grid.options.headerTemplate) ? $scope.grid.options.headerTemplate : defaultTemplate; } gridUtil.getTemplate(headerTemplate) .then(function (contents) { var template = angular.element(contents); var newElm = $compile(template)($scope); $elm.replaceWith(newElm); // And update $elm to be the new element $elm = newElm; updateHeaderReferences(); if (containerCtrl) { // Inject a reference to the header viewport (if it exists) into the grid controller for use in the horizontal scroll handler below var headerViewport = $elm[0].getElementsByClassName('ui-grid-header-viewport')[0]; if (headerViewport) { containerCtrl.headerViewport = headerViewport; angular.element(headerViewport).on('scroll', scrollHandler); $scope.$on('$destroy', function () { angular.element(headerViewport).off('scroll', scrollHandler); }); } } $scope.grid.queueRefresh(); }); function updateHeaderReferences() { containerCtrl.header = containerCtrl.colContainer.header = $elm; var headerCanvases = $elm[0].getElementsByClassName('ui-grid-header-canvas'); if (headerCanvases.length > 0) { containerCtrl.headerCanvas = containerCtrl.colContainer.headerCanvas = headerCanvases[0]; } else { containerCtrl.headerCanvas = null; } } function scrollHandler(evt) { if (uiGridCtrl.grid.isScrollingHorizontally) { return; } var newScrollLeft = gridUtil.normalizeScrollLeft(containerCtrl.headerViewport, uiGridCtrl.grid); var horizScrollPercentage = containerCtrl.colContainer.scrollHorizontal(newScrollLeft);