Skip to content

Commit a70f354

Browse files
authored
Merge pull request #303 from jeff-phillips-18/fixes
Add ability to include badges on nav items in pfVerticalNavigation
2 parents 4900570 + 348e110 commit a70f354

File tree

4 files changed

+354
-76
lines changed

4 files changed

+354
-76
lines changed

misc/examples.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,10 @@ hr {
123123
.example-info-text:first-of-type {
124124
margin-top: 10px;
125125
}
126+
127+
.example-error-background {
128+
background-color: #cc0000 !important;
129+
}
130+
.example-warning-background {
131+
background-color: #ec7a08 !important;
132+
}

src/navigation/vertical-navigation-directive.js

Lines changed: 159 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*
1919
* @param {string} brandSrc src for brand image
2020
* @param {string} brandAlt Text for product name when brand image is not available
21-
* @param {boolean} hasSubMenus Flag if there are secondary and/or tertiary navigation items, default: true
21+
* @param {boolean} showBadges Flag if badges are used on navigation items, default: false
2222
* @param {boolean} persistentSecondary Flag to use persistent secondary menus, default: false
2323
* @param {boolean} hiddenIcons Flag to not show icons on the primary menu, default: false
2424
* @param {array} items List of navigation items
@@ -27,6 +27,13 @@
2727
* <li>.iconClass - (string) Classes for icon to be shown on the menu (ex. "fa fa-dashboard")
2828
* <li>.href - (string) href link to navigate to on click
2929
* <li>.children - (array) Submenu items (same structure as top level items)
30+
* <li>.badges - (array) Badges to display for the item, badges with a zero count are not displayed.
31+
* <ul style='list-style-type: none'>
32+
* <li>.count - (number) Count to display in the badge
33+
* <li>.iconClass - (string) Class to use for showing an icon before the count
34+
* <li>.tooltip - (string) Tooltip to display for the badge
35+
* <li>.badgeClass: - (string) Additional class(es) to add to the badge container
36+
* </ul>
3037
* </ul>
3138
* @param {function} navigateCallback function(item) Callback method invoked on a navigation item click (one with no submenus)
3239
* @param {function} itemClickCallback function(item) Callback method invoked on an item click
@@ -43,7 +50,7 @@
4350
</div>
4451
<div id="verticalNavLayout" class="layout-pf layout-pf-fixed faux-layout hidden" ng-controller="vertNavController">
4552
<div pf-vertical-navigation items="navigationItems" brand-alt="ANGULAR PATTERNFLY"
46-
has-sub-menus="true" pinnable-menus="true" update-active-items-on-click="true"
53+
show-badges="true" pinnable-menus="true" update-active-items-on-click="true"
4754
navigate-callback="handleNavigateClick">
4855
<div>
4956
<ul class="nav navbar-nav">
@@ -75,7 +82,7 @@
7582
</ul>
7683
</div>
7784
</div>
78-
<div id="contentContainer" class="container-fluid container-cards-pf container-pf-nav-pf-vertical container-pf-nav-pf-vertical-with-sub-menus example-page-container">
85+
<div id="contentContainer" class="container-fluid container-cards-pf container-pf-nav-pf-vertical example-page-container">
7986
<div id="includedContent"></div>
8087
</div>
8188
</div>
@@ -92,7 +99,13 @@
9299
{
93100
title: "Dolor",
94101
iconClass : "fa fa-shield",
95-
href: "#/dolor"
102+
href: "#/dolor",
103+
badges: [
104+
{
105+
count: 1283,
106+
tooltip: "Total number of items"
107+
}
108+
]
96109
},
97110
{
98111
title: "Ipsum",
@@ -103,15 +116,35 @@
103116
children: [
104117
{
105118
title: "Recteque",
106-
href: "#/ipsum/intellegam/recteque"
119+
href: "#/ipsum/intellegam/recteque",
120+
badges: [
121+
{
122+
count: 6,
123+
tooltip: "Total number of error items",
124+
badgeClass: 'example-error-background'
125+
}
126+
]
107127
},
108128
{
109129
title: "Suavitate",
110-
href: "#/ipsum/intellegam/suavitate"
130+
href: "#/ipsum/intellegam/suavitate",
131+
badges: [
132+
{
133+
count: 2,
134+
tooltip: "Total number of items"
135+
}
136+
]
111137
},
112138
{
113139
title: "Vituperatoribus",
114-
href: "#/ipsum/intellegam/vituperatoribus"
140+
href: "#/ipsum/intellegam/vituperatoribus",
141+
badges: [
142+
{
143+
count: 18,
144+
tooltip: "Total number of warning items",
145+
badgeClass: 'example-warning-background'
146+
}
147+
]
115148
}
116149
]
117150
},
@@ -120,15 +153,51 @@
120153
children: [
121154
{
122155
title: "Exerci",
123-
href: "#/ipsum/copiosae/exerci"
156+
href: "#/ipsum/copiosae/exerci",
157+
badges: [
158+
{
159+
count: 2,
160+
tooltip: "Total number of error items",
161+
iconClass: 'pficon pficon-error-circle-o'
162+
},
163+
{
164+
count: 6,
165+
tooltip: "Total number warning error items",
166+
iconClass: 'pficon pficon-warning-triangle-o'
167+
}
168+
]
124169
},
125170
{
126171
title: "Quaeque",
127-
href: "#/ipsum/copiosae/quaeque"
172+
href: "#/ipsum/copiosae/quaeque",
173+
badges: [
174+
{
175+
count: 0,
176+
tooltip: "Total number of error items",
177+
iconClass: 'pficon pficon-error-circle-o'
178+
},
179+
{
180+
count: 4,
181+
tooltip: "Total number warning error items",
182+
iconClass: 'pficon pficon-warning-triangle-o'
183+
}
184+
]
128185
},
129186
{
130187
title: "Utroque",
131-
href: "#/ipsum/copiosae/utroque"
188+
href: "#/ipsum/copiosae/utroque",
189+
badges: [
190+
{
191+
count: 1,
192+
tooltip: "Total number of error items",
193+
iconClass: 'pficon pficon-error-circle-o'
194+
},
195+
{
196+
count: 2,
197+
tooltip: "Total number warning error items",
198+
iconClass: 'pficon pficon-warning-triangle-o'
199+
}
200+
]
132201
}
133202
]
134203
},
@@ -151,7 +220,19 @@
151220
},
152221
{
153222
title: "Accumsan",
154-
href: "#/ipsum/Accumsan"
223+
href: "#/ipsum/Accumsan",
224+
badges: [
225+
{
226+
count: 2,
227+
tooltip: "Total number of error items",
228+
iconClass: 'pficon pficon-error-circle-o'
229+
},
230+
{
231+
count: 6,
232+
tooltip: "Total number warning error items",
233+
iconClass: 'pficon pficon-warning-triangle-o'
234+
}
235+
]
155236
}
156237
]
157238
},
@@ -492,7 +573,7 @@
492573
scope: {
493574
brandSrc: '@',
494575
brandAlt: '@',
495-
hasSubMenus: '@',
576+
showBadges: '@',
496577
persistentSecondary: '@',
497578
pinnableMenus: '@',
498579
hiddenIcons: '@',
@@ -508,12 +589,13 @@
508589
controller: function ($scope) {
509590
var routeChangeListener;
510591

511-
$scope.hasSubMenus = $scope.hasSubMenus !== 'false';
592+
$scope.showBadges = $scope.showBadges === 'true';
512593
$scope.persistentSecondary = $scope.persistentSecondary === 'true';
513594
$scope.pinnableMenus = $scope.pinnableMenus === 'true';
514595
$scope.hiddenIcons = $scope.hiddenIcons === 'true';
515596
$scope.updateActiveItemsOnClick = $scope.updateActiveItemsOnClick === 'true';
516597
$scope.ignoreMobile = $scope.ignoreMobile === 'true';
598+
$scope.activeSecondary = false;
517599

518600
$scope.clearActiveItems = function () {
519601
$scope.items.forEach(function (item) {
@@ -573,11 +655,27 @@
573655
'desktop': 1200
574656
};
575657

576-
var bodyContentElement = angular.element(document.querySelector('.container-pf-nav-pf-vertical'));
658+
var getBodyContentElement = function () {
659+
return angular.element(document.querySelector('.container-pf-nav-pf-vertical'));
660+
};
661+
577662
var explicitCollapse = false;
578663
var hoverDelay = 500;
579664
var hideDelay = hoverDelay + 200;
580665

666+
var initBodyElement = function () {
667+
var bodyContentElement = getBodyContentElement();
668+
if ($scope.showBadges) {
669+
bodyContentElement.addClass('nav-pf-vertical-with-badges');
670+
}
671+
if ($scope.persistentSecondary) {
672+
bodyContentElement.addClass('nav-pf-persistent-secondary');
673+
}
674+
if ($scope.hiddenIcons) {
675+
bodyContentElement.addClass('hidden-icons-pf');
676+
}
677+
};
678+
581679
var updateMobileMenu = function (selected, secondaryItem) {
582680
$scope.items.forEach(function (item) {
583681
item.isMobileItem = false;
@@ -606,6 +704,7 @@
606704

607705
var checkNavState = function () {
608706
var width = $window.innerWidth;
707+
var bodyContentElement = getBodyContentElement();
609708

610709
// Check to see if we need to enter/exit the mobile state
611710
if (!$scope.ignoreMobile && width < breakpoints.tablet) {
@@ -640,6 +739,7 @@
640739
};
641740

642741
var collapseMenu = function () {
742+
var bodyContentElement = getBodyContentElement();
643743
$scope.navCollapsed = true;
644744

645745
//Set the body class to the correct state
@@ -649,6 +749,7 @@
649749
};
650750

651751
var expandMenu = function () {
752+
var bodyContentElement = getBodyContentElement();
652753
$scope.navCollapsed = false;
653754

654755
//Set the body class to the correct state
@@ -668,17 +769,6 @@
668769
}, 500);
669770
};
670771

671-
var setFirstChildActive = function (item) {
672-
if (item && item.children && item.children.length > 0) {
673-
if ($scope.updateActiveItemsOnClick ) {
674-
item.children[0].isActive = true;
675-
}
676-
setFirstChildActive(item.children[0]);
677-
} else if (item && $scope.navigateCallback) {
678-
$scope.navigateCallback(item);
679-
}
680-
};
681-
682772
var setParentActive = function (item) {
683773
$scope.items.forEach(function (topLevel) {
684774
if (topLevel.children) {
@@ -699,18 +789,52 @@
699789
});
700790
};
701791

702-
var navigateToItem = function (item) {
703-
var navTo = item.href;
792+
var getFirstNavigateChild = function (item) {
793+
var firstChild;
704794
if (!item.children || item.children.length < 1) {
795+
firstChild = item;
796+
} else {
797+
firstChild = getFirstNavigateChild(item.children[0]);
798+
}
799+
return firstChild;
800+
};
801+
802+
var setSecondaryItemVisible = function () {
803+
var bodyContentElement = getBodyContentElement();
804+
$scope.activeSecondary = false;
805+
806+
if ($scope.persistentSecondary && !$scope.inMobileState) {
807+
$scope.items.forEach(function (topLevel) {
808+
if (topLevel.children) {
809+
topLevel.children.forEach(function (secondLevel) {
810+
if (secondLevel.isActive) {
811+
$scope.activeSecondary = true;
812+
}
813+
});
814+
}
815+
});
816+
if ($scope.activeSecondary) {
817+
bodyContentElement.addClass('secondary-visible-pf');
818+
} else {
819+
bodyContentElement.removeClass('secondary-visible-pf');
820+
}
821+
}
822+
};
823+
824+
var navigateToItem = function (item) {
825+
var navItem = getFirstNavigateChild(item);
826+
var navTo;
827+
if (navItem) {
705828
$scope.showMobileNav = false;
829+
navTo = navItem.href;
706830
if (navTo) {
707831
if (navTo.startsWith('#/')) {
708832
navTo = navTo.substring(2);
709833
}
710834
location.path(navTo);
711835
}
712836
if ($scope.navigateCallback) {
713-
$scope.navigateCallback(item);
837+
$scope.navigateCallback(navItem);
714838
}
715839
}
716840

@@ -720,11 +844,11 @@
720844

721845
if ($scope.updateActiveItemsOnClick ) {
722846
$scope.clearActiveItems();
723-
item.isActive = true;
724-
setParentActive(item);
847+
navItem.isActive = true;
848+
setParentActive(navItem);
849+
setSecondaryItemVisible();
725850
}
726-
727-
setFirstChildActive(item);
851+
setSecondaryItemVisible();
728852
};
729853

730854
var primaryHover = function () {
@@ -752,6 +876,7 @@
752876
};
753877

754878
var updateSecondaryCollapsedState = function (setCollapsed, collapsedItem) {
879+
var bodyContentElement = getBodyContentElement();
755880
if (collapsedItem) {
756881
collapsedItem.secondaryCollapsed = setCollapsed;
757882
}
@@ -773,6 +898,7 @@
773898
};
774899

775900
var updateTertiaryCollapsedState = function (setCollapsed, collapsedItem) {
901+
var bodyContentElement = getBodyContentElement();
776902
if (collapsedItem) {
777903
collapsedItem.tertiaryCollapsed = setCollapsed;
778904
}
@@ -808,16 +934,6 @@
808934
$scope.navCollapsed = false;
809935
$scope.forceHidden = false;
810936

811-
if ($scope.hasSubMenus) {
812-
bodyContentElement.addClass('container-pf-nav-pf-vertical-with-sub-menus');
813-
}
814-
if ($scope.persistentSecondary) {
815-
bodyContentElement.addClass('nav-pf-persistent-secondary');
816-
}
817-
if ($scope.hiddenIcons) {
818-
bodyContentElement.addClass('hidden-icons-pf');
819-
}
820-
821937
$scope.handleNavBarToggleClick = function () {
822938

823939
if ($scope.inMobileState) {
@@ -981,6 +1097,7 @@
9811097
event.stopImmediatePropagation();
9821098
};
9831099

1100+
initBodyElement();
9841101
checkNavState();
9851102

9861103
angular.element($window).bind('resize', function () {

0 commit comments

Comments
 (0)