Skip to content

Commit

Permalink
Enhance(gridMenu): further refactor of menu logic, onclick handlers
Browse files Browse the repository at this point in the history
Move handlers from column menu into grid menu, remove obsolete code,
provide 'menu-hidden' event to allow better tracking of menu state.

Extensions to exporter to better take advantage of grid menu.
  • Loading branch information
PaulL1 committed Oct 5, 2014
1 parent 08c522b commit f65beb0
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 93 deletions.
71 changes: 71 additions & 0 deletions misc/tutorial/206_exporting_data.ngdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
@ngdoc overview
@name Tutorial: 206 Exporting Data With Native UI
@description The exporter feature allows data to be exported from the grid in
csv or pdf format. The exporter can export all data, visible data or selected data.

To use the exporter you need to include the ui-grid-exporter directive on
your grid. If you want to export selected rows you must include the ui-grid-selection
directive on your grid. If you want to export as PDF you need to have installed pdfMake,
available through:
<pre> bower install pdfmake </pre>

The options and API for exporter can be found at {@link api/ui.grid.exporter ui.grid.exporter}.

The exporter adds menu items to the grid menu, to use the native UI you need to enable
the grid menu using the gridOption `enableGridMenu`

@example
In this example we provide a custom UI for calling the exporter, and we tailor
the way the returned data behaves.

<example module="app">
<file name="app.js">
var app = angular.module('app', ['ngAnimate', 'ui.grid', 'ui.grid.selection', 'ui.grid.exporter']);

app.controller('MainCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.gridOptions = {
columnDefs: [
{ field: 'name' },
{ field: 'gender', visible: false},
{ field: 'company' }
],
enableGridMenu: true,
exporterLinkLabel: 'get your csv here',
exporterPdfDefaultStyle: {fontSize: 9},
exporterPdfTableStyle: {margin: [30, 30, 30, 30]},
exporterPdfTableHeaderStyle: {fontSize: 10, bold: true, italics: true, color: 'red'},
exporterPdfOrientation: 'portrait',
exporterPdfPageSize: 'LETTER',
exporterPdfMaxGridWidth: 500,
exporterCsvLinkElement: angular.element(document.querySelectorAll(".custom-csv-link-location")),
onRegisterApi: function(gridApi){
$scope.gridApi = gridApi;
}
};

$http.get('/data/100.json')
.success(function(data) {
$scope.gridOptions.data = data;
});

}]);
</file>

<file name="index.html">
<div ng-controller="MainCtrl">
<div class="custom-csv-link-location">
<label>Your CSV will show below:</label>
<span class="ui-grid-exporter-csv-link">&nbsp</span>
</div>

<div ui-grid="gridOptions" ui-grid-selection ui-grid-exporter class="grid"></div>
</div>
</file>

<file name="main.css">
.grid {
width: 500px;
height: 400px;
}
</file>
</example>
6 changes: 3 additions & 3 deletions misc/tutorial/304_grid_menu.ngdoc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ if at least one row is selected.

app.controller('MainCtrl', ['$scope', '$http', '$interval', function ($scope, $http, $interval) {
$scope.gridOptions = {
exporterMenuCsvExport: false,
exporterMenuCsv: false,
enableGridMenu: true,
gridMenuCustomItems: [
{
Expand Down Expand Up @@ -79,8 +79,8 @@ if at least one row is selected.
gridTestUtils.expectHeaderColumnCount( 'grid1', 3 );
});

it('grid1 grid menu should have 10 items', function () {
gridTestUtils.expectVisibleGridMenuItems( 'grid1', 10 );
it('grid1 grid menu should have 8 items', function () {
gridTestUtils.expectVisibleGridMenuItems( 'grid1', 8 );
});

it('grid1 hide then show gender column', function () {
Expand Down
4 changes: 1 addition & 3 deletions misc/tutorial/306_exporting_data_complex.ngdoc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@ngdoc overview
@name Tutorial: 306 Exporting Data
@name Tutorial: 306 Exporting Data With Custom UI
@description The exporter feature allows data to be exported from the grid in
csv or pdf format. The exporter can export all data, visible data or selected data.

Expand Down Expand Up @@ -27,9 +27,7 @@ the way the returned data behaves.
{ field: 'gender', visible: false},
{ field: 'company' }
],
exporterButtonLabel: 'Export now',
exporterLinkLabel: 'get your csv here',
exporterSuppressButton: true,
exporterPdfDefaultStyle: {fontSize: 9},
exporterPdfTableStyle: {margin: [30, 30, 30, 30]},
exporterPdfTableHeaderStyle: {fontSize: 10, bold: true, italics: true, color: 'red'},
Expand Down
18 changes: 16 additions & 2 deletions src/features/exporter/js/exporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,13 @@
},


/**
* @ngdoc object
* @name exporterCsvLinkElement
* @propertyOf ui.grid.exporter.api:GridOptions
* @description The element that the csv link should be placed into.
* Mandatory if using the native UI.
*/
/**
* @ngdoc function
* @name csvExport
Expand All @@ -397,9 +404,16 @@
var exportColumnHeaders = this.getColumnHeaders(grid, colTypes);
var exportData = this.getData(grid, rowTypes, colTypes);
var csvContent = this.formatAsCsv(exportColumnHeaders, exportData);
this.renderCsvLink(grid, csvContent, $elm);

// this.grid.exporter.$scope.$broadcast('clearExporterMenu');
if ( !$elm && grid.options.exporterCsvLinkElement ){
$elm = grid.options.exporterCsvLinkElement;
}

if ( $elm ){
this.renderCsvLink(grid, csvContent, $elm);
} else {
$log.error( 'Exporter asked to export as csv, but no element provided. Perhaps you should set gridOptions.exporterCsvLinkElement?')
; }
},


Expand Down
35 changes: 24 additions & 11 deletions src/js/core/directives/ui-grid-column-menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -282,16 +282,19 @@ function ( i18nService, uiGridConstants, gridUtil ) {

var containerScrolLeft = renderContainerElm.querySelectorAll('.ui-grid-viewport')[0].scrollLeft;

var myWidth = $scope.lastWidth ? $scope.lastWidth : 170;
var paddingRight = $scope.lastPaddingRight ? $scope.lastPaddingRight : 10;
// default value the last width for _this_ column, otherwise last width for _any_ column, otherwise default to 170
var myWidth = $scope.col.lastMenuWidth ? $scope.col.lastMenuWidth : ( $scope.lastMenuWidth ? $scope.lastMenuWidth : 170);
var paddingRight = $scope.col.lastMenuPaddingRight ? $scope.col.lastMenuPaddingRight : ( $scope.lastMenuPaddingRight ? $scope.lastMenuPaddingRight : 10);
if (menu.length !== 0){
myWidth = gridUtil.elementWidth(menu, true);
$scope.lastWidth = myWidth;
$scope.lastMenuWidth = myWidth;
$scope.col.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.lastPaddingRight = paddingRight;
$scope.lastMenuPaddingRight = paddingRight;
$scope.col.lastMenuPaddingRight = paddingRight;
}

$elm.css('left', (positionData.left + renderContainerOffset - containerScrolLeft + positionData.width - myWidth + paddingRight) + 'px');
Expand All @@ -304,8 +307,8 @@ function ( i18nService, uiGridConstants, gridUtil ) {
}])


.directive('uiGridColumnMenu', ['$log', '$timeout', '$window', '$document', '$injector', 'gridUtil', 'uiGridConstants', 'uiGridColumnMenuService',
function ($log, $timeout, $window, $document, $injector, gridUtil, uiGridConstants, uiGridColumnMenuService) {
.directive('uiGridColumnMenu', ['$log', '$timeout', 'gridUtil', 'uiGridConstants', 'uiGridColumnMenuService',
function ($log, $timeout, gridUtil, uiGridConstants, uiGridColumnMenuService) {
/**
* @ngdoc directive
* @name ui.grid.directive:uiGridColumnMenu
Expand Down Expand Up @@ -348,7 +351,7 @@ function ($log, $timeout, $window, $document, $injector, gridUtil, uiGridConstan
$scope.col = column;

// Remove an existing document click handler
$document.off('click', documentClick);
// $document.off('click', documentClick);

// Get the position information for the column element
var colElementPosition = uiGridColumnMenuService.getColumnElementPosition( $scope, column, $columnElement );
Expand All @@ -373,7 +376,7 @@ function ($log, $timeout, $window, $document, $injector, gridUtil, uiGridConstan
}

// Hide the menu on a click on the document
$document.on('click', documentClick);
// $document.on('click', documentClick);
};


Expand All @@ -382,14 +385,20 @@ function ($log, $timeout, $window, $document, $injector, gridUtil, uiGridConstan
* @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() {
$scope.hideMenu = function( broadcastTrigger ) {
delete $scope.col;
$scope.menuShown = false;
$scope.$broadcast('hide-menu');

if ( !broadcastTrigger ){
$scope.$broadcast('hide-menu');
}
};


/*
function documentClick() {
$scope.$apply($scope.hideMenu);
$document.off('click', documentClick);
Expand All @@ -412,6 +421,10 @@ function ($log, $timeout, $window, $document, $injector, gridUtil, uiGridConstan
angular.element($window).off('resize', resizeHandler);
$document.off('click', documentClick);
});
*/
$scope.$on('menu-hidden', function() {
$scope.hideMenu( true );
});


/* Column methods */
Expand Down
48 changes: 13 additions & 35 deletions src/js/core/directives/ui-grid-menu-button.js
Original file line number Diff line number Diff line change
Expand Up @@ -279,44 +279,22 @@ function ($log, gridUtil, uiGridConstants, uiGridGridMenuService) {

uiGridGridMenuService.initialize($scope, uiGridCtrl.grid);

$scope.shown = false;

$scope.openMenu = function () {
$scope.menuItems = uiGridGridMenuService.getMenuItems( $scope );
$scope.$broadcast('openGridMenu');
$scope.toggleMenu = function () {
if ( $scope.shown ){
$scope.$broadcast('hide-menu');
$scope.shown = false;
} else {
$scope.menuItems = uiGridGridMenuService.getMenuItems( $scope );
$scope.$broadcast('show-menu');
$scope.shown = true;
}
};
}
};

}])
.directive('uiGridMenuHandler', ['$log', 'gridUtil', 'uiGridConstants', '$timeout',
function ($log, gridUtil, uiGridConstants, $timeout) {

return {
priority: 0,
require: ['?^uiGrid', 'uiGridMenu'],
link: function ($scope, $elm, $attrs, controllers) {
var uiGridCtrl = controllers[0];
var uiGridMenuCtrl = controllers[1];

$scope.$on('openGridMenu', function () {
uiGridMenuCtrl.showMenu();

$timeout(function () {
var gridElm = uiGridCtrl.grid.element;
var gridWidth = gridUtil.elementWidth(gridElm, true);
var menuWidth = 200; // calculate this later

// Put the menu inside the right of the grid
$elm.css('left', gridWidth - menuWidth + 'px');

// Put the menu at the top of the grid but adjust for the border
$elm.css('top', '-1px');
});
});

$scope.$on('hideGridMenu', function () {
uiGridMenuCtrl.hideMenu();
});
$scope.$on('menu-hidden', function() {
$scope.shown = false;
});
}
};

Expand Down
79 changes: 44 additions & 35 deletions src/js/core/directives/ui-grid-menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,57 +42,66 @@ angular.module('ui.grid')
templateUrl: 'ui-grid/uiGridMenu',
replace: false,
link: function ($scope, $elm, $attrs, uiGridCtrl) {
var self = this;
gridUtil.enableAnimations($elm);

if (typeof($scope.autoHide) === 'undefined' || $scope.autoHide === undefined) {
$scope.autoHide = true;
}

// *** Show/Hide functions ******
self.showMenu = $scope.showMenu = function() {
$scope.shown = true;

if ($scope.autoHide) {
angular.element($window).on('resize', $scope.hideMenu);
}
// Turn off an existing dpcument click handler
angular.element(document).off('click', applyHideMenu);

$scope.$on('hide-menu', function () {
// Turn on the document click handler, but in a timeout so it doesn't apply to THIS click if there is one
$timeout(function() {
angular.element(document).on('click', applyHideMenu);
});
};

self.hideMenu = $scope.hideMenu = function() {
$scope.shown = false;
});
$scope.$emit('menu-hidden');
angular.element(document).off('click', applyHideMenu);
};

$scope.$on('show-menu', function () {
$scope.shown = true;
$scope.$on('hide-menu', function () {
$scope.hideMenu();
});

$scope.$on('$destroy', function() {
angular.element($window).off('resize', $scope.hideMenu);
$scope.$on('show-menu', function () {
$scope.showMenu();
});
},
controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
var self = this;

self.hideMenu = $scope.hideMenu = function() {
$scope.shown = false;
};

function documentClick() {

// *** Auto hide when click elsewhere ******
var applyHideMenu = function(){
$scope.$apply(function () {
self.hideMenu();
angular.element(document).off('click', documentClick);
$scope.hideMenu();
});
};

if (typeof($scope.autoHide) === 'undefined' || $scope.autoHide === undefined) {
$scope.autoHide = true;
}

self.showMenu = $scope.showMenu = function() {
$scope.shown = true;

// Turn off an existing dpcument click handler
angular.element(document).off('click', documentClick);

// Turn on the document click handler, but in a timeout so it doesn't apply to THIS click if there is one
$timeout(function() {
angular.element(document).on('click', documentClick);
});
};
if ($scope.autoHide) {
angular.element($window).on('resize', applyHideMenu);
}

$scope.$on('$destroy', function () {
angular.element(document).off('click', documentClick);
angular.element(document).off('click', applyHideMenu);
});


$scope.$on('$destroy', function() {
angular.element($window).off('resize', applyHideMenu);
});
},


controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
var self = this;
}]
};

Expand Down Expand Up @@ -173,7 +182,7 @@ angular.module('ui.grid')

$scope.action.call(context, $event, title);

uiGridMenuCtrl.hideMenu();
$scope.$emit('hide-menu');
}
};

Expand Down
Loading

0 comments on commit f65beb0

Please sign in to comment.