Skip to content

Commit f8d643e

Browse files
Add ability to have actions pulldown menu in pfDataList directive
1 parent 53de6ff commit f8d643e

File tree

11 files changed

+649
-101
lines changed

11 files changed

+649
-101
lines changed

dist/angular-patternfly.js

Lines changed: 184 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3200,7 +3200,8 @@ angular.module('patternfly.validation', []).directive('pfValidation', ["$timeout
32003200
* Directive for rendering a data list.
32013201
* <br><br>
32023202
*
3203-
* @param {object} config configuration settings for the data list:<br/>
3203+
* @param {array} items Array of items to display in the list
3204+
* @param {object} config Configuration settings for the data list:
32043205
* <ul style='list-style-type: none'>
32053206
* <li>.showSelectBox - (boolean) Show item selection boxes for each item, default is true
32063207
* <li>.selectItems - (boolean) Allow row selection, default is false
@@ -3216,28 +3217,35 @@ angular.module('patternfly.validation', []).directive('pfValidation', ["$timeout
32163217
* <li>.onClick - ( function(item, event) ) Called to notify when an item is clicked, default is none
32173218
* <li>.onDblClick - ( function(item, event) ) Called to notify when an item is double clicked, default is none
32183219
* </ul>
3219-
*
3220-
* @param {Array} items the data to be shown in the data list<br/>
3221-
*
3220+
* @param {array} actions List of actions for dropdown menu in each row
3221+
* <ul style='list-style-type: none'>
3222+
* <li>.name - (String) The name of the action, displayed on the button
3223+
* <li>.title - (String) Optional title, used for the tooltip
3224+
* <li>.actionFn - (function(action)) Function to invoke when the action selected
3225+
* <li>.isVisible - (Boolean) set to true to disable the action
3226+
* <li>.isDisabled - (Boolean) set to true to disable the action
3227+
* <li>.isSeparator - (Boolean) set to true if this is a placeholder for a separator rather than an action
3228+
* </ul>
3229+
* @param {function (action, item))} updateActionForItemFn function(action, item) Used to update an action based on the current item
32223230
* @example
32233231
<example module="patternfly.views" deps="patternfly.utils">
32243232
<file name="index.html">
3225-
<div ng-controller="ViewCtrl" class="row" style="display:inline-block; width: 100%;">
3226-
<div class="col-md-12">
3227-
<div pf-data-list id="exampleDataList" config="config" items="items">
3228-
<div class="col-md-12 cfme-row-column">
3229-
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3 list-column">
3230-
<span>{{item.name}}</span>
3231-
</div>
3232-
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3 list-column">
3233-
<span>{{item.address}}</span>
3234-
</div>
3235-
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3 list-column">
3236-
<span>{{item.city}}</span>
3237-
</div>
3238-
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3 list-column">
3239-
<span>{{item.state}}</span>
3240-
</div>
3233+
<div ng-controller="ViewCtrl" class="row example-container">
3234+
<div class="col-md-12 list-view-container">
3235+
<div pf-data-list class="example-data-list" id="exampleDataList" config="config" items="items" actions="actions">
3236+
<div class="row">
3237+
<div class="col-md-3">
3238+
<span>{{item.name}}</span>
3239+
</div>
3240+
<div class="col-md-3">
3241+
<span>{{item.address}}</span>
3242+
</div>
3243+
<div class="col-md-3">
3244+
<span>{{item.city}}</span>
3245+
</div>
3246+
<div class="col-md-3">
3247+
<span>{{item.state}}</span>
3248+
</div>
32413249
</div>
32423250
</div>
32433251
</div>
@@ -3369,36 +3377,144 @@ angular.module('patternfly.validation', []).directive('pfValidation', ["$timeout
33693377
state: "Pennsylvania"
33703378
},
33713379
{
3372-
name: "Judy Green",
3373-
address: "2 Apple Boulevard",
3374-
city: "Cincinatti",
3375-
state: "Ohio"
3380+
name: "Linda McGovern",
3381+
address: "22 Oak Street",
3382+
city: "Denver",
3383+
state: "Colorado"
3384+
},
3385+
{
3386+
name: "Jim Beam",
3387+
address: "72 Bourbon Way",
3388+
city: "Nashville",
3389+
state: "Tennessee"
3390+
},
3391+
{
3392+
name: "Holly Nichols",
3393+
address: "21 Jump Street",
3394+
city: "Hollywood",
3395+
state: "California"
3396+
},
3397+
{
3398+
name: "Marie Edwards",
3399+
address: "17 Cross Street",
3400+
city: "Boston",
3401+
state: "Massachusetts"
33763402
},
33773403
{
33783404
name: "Pat Thomas",
33793405
address: "50 Second Street",
33803406
city: "New York",
33813407
state: "New York"
33823408
},
3383-
]
3409+
];
3410+
3411+
var performAction = function (action, item) {
3412+
$scope.eventText = item.name + " : " + action.name + "\n" + $scope.eventText;
3413+
};
3414+
3415+
$scope.actions = [
3416+
{
3417+
name: 'Action',
3418+
title: 'Perform an action',
3419+
actionFn: performAction
3420+
},
3421+
{
3422+
name: 'Another Action',
3423+
title: 'Do something else',
3424+
actionFn: performAction
3425+
},
3426+
{
3427+
name: 'Disabled Action',
3428+
title: 'Unavailable action',
3429+
actionFn: performAction,
3430+
isDisabled: true
3431+
},
3432+
{
3433+
name: 'Something Else',
3434+
title: '',
3435+
actionFn: performAction
3436+
},
3437+
{
3438+
isSeparator: true
3439+
},
3440+
{
3441+
name: 'Grouped Action 1',
3442+
title: 'Do something',
3443+
actionFn: performAction
3444+
},
3445+
{
3446+
name: 'Grouped Action 2',
3447+
title: 'Do something similar',
3448+
actionFn: performAction
3449+
}
3450+
];
33843451
}
33853452
]);
33863453
</file>
33873454
</example>
33883455
*/
3389-
angular.module('patternfly.views').directive('pfDataList', ["pfUtils", function (pfUtils) {
3456+
angular.module('patternfly.views').directive('pfDataList',
3457+
["$timeout", "$window", "pfUtils", function ($timeout, $window, pfUtils) {
33903458
'use strict';
33913459
return {
33923460
restrict: 'A',
33933461
scope: {
33943462
config: '=?',
33953463
items: '=',
3396-
eventId: '@id'
3464+
actions: '=?',
3465+
updateActionForItemFn: '=?'
33973466
},
33983467
transclude: true,
33993468
templateUrl: 'views/datalist/data-list.html',
3400-
controller: ['$scope',
3401-
function ($scope) {
3469+
controller:
3470+
["$scope", "$element", function ($scope, $element) {
3471+
var setDropMenuLocation = function (parentDiv) {
3472+
var dropButton = parentDiv.querySelector('.dropdown-toggle');
3473+
var dropMenu = parentDiv.querySelector('.dropdown-menu');
3474+
var buttonRect = dropButton.getBoundingClientRect();
3475+
var menuRect = dropMenu.getBoundingClientRect();
3476+
var top = buttonRect.top + buttonRect.height;
3477+
var left = buttonRect.left + buttonRect.width - menuRect.width;
3478+
var docHeight = $window.innerHeight;
3479+
3480+
if (top + menuRect.height > docHeight) {
3481+
top = docHeight - menuRect.height;
3482+
}
3483+
3484+
dropMenu.style.top = top + "px";
3485+
dropMenu.style.left = left + "px";
3486+
};
3487+
3488+
var hideOnScroll = function () {
3489+
$scope.prevMenuItem.showMenu = false;
3490+
angular.element(angular.element($element).find('.data-list-pf')[0]).unbind("scroll", hideOnScroll);
3491+
angular.element($window).unbind("scroll", hideOnScroll);
3492+
$scope.$apply();
3493+
};
3494+
3495+
var showActionMenu = function (item, event) {
3496+
item.showMenu = true;
3497+
$scope.prevMenuItem = item;
3498+
3499+
$timeout(function () {
3500+
var parentDiv = undefined;
3501+
var nextElement;
3502+
3503+
nextElement = event.toElement;
3504+
while (nextElement && !parentDiv) {
3505+
if (nextElement.className.indexOf('list-menu') === 0) {
3506+
parentDiv = nextElement;
3507+
setDropMenuLocation (parentDiv);
3508+
}
3509+
nextElement = nextElement.parentElement;
3510+
}
3511+
3512+
angular.element(angular.element($element).find('.data-list-pf')[0]).bind("scroll", hideOnScroll);
3513+
angular.element($window).bind("scroll", hideOnScroll);
3514+
});
3515+
3516+
};
3517+
34023518
$scope.defaultConfig = {
34033519
selectItems: false,
34043520
multiSelect: false,
@@ -3421,8 +3537,40 @@ angular.module('patternfly.views').directive('pfDataList', ["pfUtils", function
34213537
'Illegal use of pfDataList directive! ' +
34223538
'Cannot allow both select box and click selection in the same data list.');
34233539
}
3424-
}
3425-
],
3540+
3541+
$scope.handleAction = function (action, item) {
3542+
if (action && action.actionFn && (action.isDisabled !== true)) {
3543+
action.actionFn(action, item);
3544+
}
3545+
};
3546+
3547+
$scope.updateActions = function (item) {
3548+
$scope.actionItem = item;
3549+
if (typeof $scope.updateActionForItemFn === 'function') {
3550+
$scope.actions.forEach(function (action) {
3551+
$scope.updateActionForItemFn(action, item);
3552+
});
3553+
}
3554+
};
3555+
3556+
$scope.setupActions = function (item, event) {
3557+
if ($scope.prevMenuItem) {
3558+
$scope.prevMenuItem.showMenu = false;
3559+
$scope.prevMenuItem = undefined;
3560+
}
3561+
3562+
// Ignore disabled items completely
3563+
if ($scope.checkDisabled(item)) {
3564+
return;
3565+
}
3566+
3567+
// update the actions based on the current item
3568+
$scope.updateActions(item);
3569+
3570+
// Show the action menu for the item
3571+
showActionMenu(item, event);
3572+
};
3573+
}],
34263574

34273575
link: function (scope, element, attrs) {
34283576
attrs.$observe('config', function () {
@@ -3713,7 +3861,8 @@ angular.module('patternfly.views').directive('pfDataList', ["pfUtils", function
37133861
</file>
37143862
</example>
37153863
*/
3716-
angular.module('patternfly.views').directive('pfDataTiles', ["pfUtils", function (pfUtils) {
3864+
angular.module('patternfly.views').directive('pfDataTiles',
3865+
["pfUtils", function (pfUtils) {
37173866
'use strict';
37183867
return {
37193868
restrict: 'A',
@@ -3902,8 +4051,8 @@ angular.module('patternfly.views').directive('pfDataTiles', ["pfUtils", function
39024051
<label class="events-label">Valid Items: </label>
39034052
</div>
39044053
<div class="col-md-12 list-view-container" ng-if="viewType == 'listView'">
3905-
<div pf-data-list class="row" config="listConfig" items="items">
3906-
<div class="row list-row">
4054+
<div pf-data-list config="listConfig" items="items">
4055+
<div class="row">
39074056
<div class="col-md-3">
39084057
<span>{{item.name}}</span>
39094058
</div>
@@ -4423,7 +4572,7 @@ angular.module('patternfly.views').directive('pfDataToolbar',
44234572
'use strict';
44244573

44254574
$templateCache.put('views/datalist/data-list.html',
4426-
"<div class=data-list-pf><div class=list-group-item ng-repeat=\"item in items track by $index\" ng-class=\"{'pf-selectable': selectItems, 'active': isSelected(item), 'disabled': checkDisabled(item)}\"><div class=\"row list-row\"><div pf-transclude=parent class=list-content ng-class=\"{'with-check-box': config.showSelectBox, 'with-menu':config.showActionMenus}\" ng-click=\"itemClick($event, item)\" ng-dblclick=\"dblClick($event, item)\"></div><div class=list-check-box ng-if=config.showSelectBox style=\"padding-top: {{(config.rowHeight - 32) / 2}}px\"><input type=checkbox value=item.selected ng-model=item.selected ng-disabled=checkDisabled(item) ng-change=\"checkBoxChange(item)\"></div></div></div></div>"
4575+
"<div class=data-list-pf><div class=list-group-item ng-repeat=\"item in items track by $index\" ng-class=\"{'pf-selectable': selectItems, 'active': isSelected(item), 'disabled': checkDisabled(item)}\"><div class=list-row><div pf-transclude=parent class=list-content ng-class=\"{'with-check-box': config.showSelectBox, 'with-menu':actions && actions.length > 0}\" ng-click=\"itemClick($event, item)\" ng-dblclick=\"dblClick($event, item)\"></div><div class=list-check-box ng-if=config.showSelectBox style=\"padding-top: {{(config.rowHeight - 32) / 2}}px\"><input type=checkbox value=item.selected ng-model=item.selected ng-disabled=checkDisabled(item) ng-change=\"checkBoxChange(item)\"></div><div class=\"list-menu dropdown btn-group {{$index}}\" ng-if=\"actions && actions.length > 0\" ng-class=\"{'disabled': checkDisabled(item)}\"><button type=button class=\"btn btn-link dropdown-toggle\" data-toggle=dropdown aria-haspopup=true aria-expanded=false ng-click=\"setupActions(item, $event)\"><span class=\"fa fa-ellipsis-v\"></span></button><ul class=dropdown-menu ng-if=item.showMenu><li ng-repeat=\"action in actions\" ng-if=\"action.isVisible !== false\" role=\"{{action.isSeparator === true ? 'separator' : 'menuitem'}}\" ng-class=\"{'divider': (action.isSeparator === true), 'disabled': (action.isDisabled === true)}\"><a ng-if=\"action.isSeparator !== true\" href=# title={{action.title}} ng-click=\"handleAction(action, item)\">{{action.name}}</a></li></ul></div></div></div></div>"
44274576
);
44284577

44294578

dist/angular-patternfly.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/styles/angular-patternfly.css

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
background: #fff;
104104
overflow-x: hidden;
105105
overflow-y: auto;
106+
height: 100%;
106107
padding-bottom: 1px;
107108
}
108109
.data-list-pf .list-row {
@@ -112,21 +113,19 @@
112113
width: 100%;
113114
}
114115
.data-list-pf .list-content {
115-
left: 15px;
116+
margin-left: 15px;
116117
position: relative;
117118
}
118119
.data-list-pf .list-content.with-check-box {
119120
border-left: solid 2px #d2d2d2;
120-
left: 30px;
121-
margin-left: 10px;
121+
margin-left: 35px;
122+
padding-left: 5px;
122123
}
123124
.data-list-pf .list-content.with-menu {
124-
margin-right: 30px;
125-
right: 15px;
125+
margin-right: 10px;
126126
}
127127
.data-list-pf .list-check-box {
128128
bottom: 0px;
129-
left: 20px;
130129
position: absolute;
131130
top: 0px;
132131
width: 20px;
@@ -172,6 +171,43 @@
172171
padding-right: 5px;
173172
}
174173

174+
.data-list-pf .list-menu {
175+
bottom: 0px;
176+
position: absolute;
177+
right: 0px;
178+
top: 0px;
179+
}
180+
181+
.data-list-pf .list-menu .btn-link {
182+
color: #222;
183+
font-size: 16px;
184+
line-height: 1;
185+
padding: 4px 0;
186+
}
187+
188+
.data-list-pf .list-menu .btn-link:hover {
189+
color: #0099d3;
190+
}
191+
192+
.data-list-pf .list-menu.disabled .btn-link,
193+
.data-list-pf .list-menu.disabled .btn-link:hover {
194+
color: #999999;
195+
cursor: not-allowed;
196+
}
197+
198+
.data-list-pf .list-menu .dropdown-menu {
199+
cursor: pointer;
200+
font-size: 12px;
201+
left: inherit;
202+
line-height: 7px;
203+
padding: 0;
204+
position: fixed;
205+
}
206+
207+
.data-list-pf .list-menu li {
208+
color: #000000;
209+
}
210+
175211
.tiles-view-pf {
176212
overflow: auto;
177213
padding-top: 20px;

0 commit comments

Comments
 (0)