Add accordion side menu with location highlight, to top nav

This forum is for all Flare issues not related to any of the other categories.
Post Reply
minicyclist
Propeller Head
Posts: 60
Joined: Wed Apr 09, 2014 3:51 pm

Add accordion side menu with location highlight, to top nav

Post by minicyclist »

Hi,

Due to customer feedback, I'd like to add an accordion style left menu to our top nav. The menu should be expandable to view the full hierarchy and should highlight the page that the user is on. The template we currently use has a side menu but it uses the menu proxy and is not collapsible.

I know this problem has been discussed before with solutions including using Foundation and Smartmenus, but I've been unable to get these working in Flare 2018 r2. I've also tried to display the hidden side nav but it won't highlight the current page.

The closest I've come is Dave Lee's Smartmenu solution: viewtopic.php?f=9&t=21607 but only the top level of the TOC is displaying and I can't see any expand/collapse buttons.

Grateful for tips.

Thanks,
Ian
clpha6
Propeller Head
Posts: 20
Joined: Thu May 11, 2017 10:43 am

Re: Add accordion side menu with location highlight, to top

Post by clpha6 »

I was looking for something similar, and was using an unwieldy (very, very long) menu proxy. I found this last week, and implemented the "Employee Handbook" template into what I had. My left nav menu now opens accordion style. In my case, users will never be able to access the help on a mobile device, so I disabled mobile view. With mobile view still available, the left nav menu turns into the hamburger menu.

https://www.madcapsoftware.com/download ... templates/
Nita Beck
Senior Propellus Maximus
Posts: 3669
Joined: Thu Feb 02, 2006 9:57 am
Location: Pittsford, NY

Re: Add accordion side menu with location highlight, to top

Post by Nita Beck »

Thanks for posting. I'm trying to make a collapsible side menu as well and just haven't gotten Dave's solution to quite work. I'll go check out the template project you tried.

EDITED: Well, scratch that. The Employee Handbook template project does not produce Top Nav output with a collapsible/expandable side menu positioned at the left. It produces Side Nav output.

I find that many Flare users confuse Side Nav with a side menu positioned at left.
Nita
Image
RETIRED, but still fond of all the Flare friends I've made. See you around now and then!
NorthEast
Master Propellus Maximus
Posts: 6365
Joined: Mon Mar 05, 2007 8:33 am

Re: Add accordion side menu with location highlight, to top

Post by NorthEast »

The smartmenus solution was from 4 years ago, before MadCap added the Side Nav skin.

So I guess the first question is - as Side Nav is available now, why not just use that?

As you're probably aware, you can't do what you want out of the box.
The Side Nav control isn't available as a separate component/skin like the menu proxy / skin.
NorthEast
Master Propellus Maximus
Posts: 6365
Joined: Mon Mar 05, 2007 8:33 am

Re: Add accordion side menu with location highlight, to top

Post by NorthEast »

Nita Beck wrote:Thanks for posting. I'm trying to make a collapsible side menu as well and just haven't gotten Dave's solution to quite work. I'll go check out the template project you tried.
The template project is just Side Nav.
Nita Beck
Senior Propellus Maximus
Posts: 3669
Joined: Thu Feb 02, 2006 9:57 am
Location: Pittsford, NY

Re: Add accordion side menu with location highlight, to top

Post by Nita Beck »

Hi Dave. Yes, I just discovered that and I amended my original post.

My client does not want to move their very, very large knowledge base, whose presentation and navigation have been spec-ed out by a UX designer, from Top Nav to Side Nav. I'm stuck with Top Nav, but I'm trying to address the request for making the side menus, positioned at left, collapse/expand. Just can't seem to get there yet.
Nita
Image
RETIRED, but still fond of all the Flare friends I've made. See you around now and then!
clpha6
Propeller Head
Posts: 20
Joined: Thu May 11, 2017 10:43 am

Re: Add accordion side menu with location highlight, to top

Post by clpha6 »

Nita Beck wrote:Thanks for posting. I'm trying to make a collapsible side menu as well and just haven't gotten Dave's solution to quite work. I'll go check out the template project you tried.

EDITED: Well, scratch that. The Employee Handbook template project does not produce Top Nav output with a collapsible/expandable side menu positioned at the left. It produces Side Nav output.

I find that many Flare users confuse Side Nav with a side menu positioned at left.
... Sorry about that! I didn't notice. It worked with what I already had, just had to change a few things to get it all to work properly. I always forget if I started with side nav or top nav. I suppose the fact that my skin is called "Side-Navigation" should be a clue!
clpha6
Propeller Head
Posts: 20
Joined: Thu May 11, 2017 10:43 am

Re: Add accordion side menu with location highlight, to top

Post by clpha6 »

Nita Beck wrote:Hi Dave. Yes, I just discovered that and I amended my original post.

My client does not want to move their very, very large knowledge base, whose presentation and navigation have been spec-ed out by a UX designer, from Top Nav to Side Nav. I'm stuck with Top Nav, but I'm trying to address the request for making the side menus, positioned at left, collapse/expand. Just can't seem to get there yet.
I had been doing something very clunky. I had three or four different Master Pages, each with a menu proxy that opened to a different level. But the side menu flashed a lot, moved up/down... it was ugly. But I couldn't have everything visible all at once. It was too much.
NorthEast
Master Propellus Maximus
Posts: 6365
Joined: Mon Mar 05, 2007 8:33 am

Re: Add accordion side menu with location highlight, to top

Post by NorthEast »

Nita Beck wrote:My client does not want to move their very, very large knowledge base, whose presentation and navigation have been spec-ed out by a UX designer, from Top Nav to Side Nav. I'm stuck with Top Nav, but I'm trying to address the request for making the side menus, positioned at left, collapse/expand. Just can't seem to get there yet.
Pop in a feature request asking if the menu proxy skin can generate an expand/collapse menu like the Side Nav.

The Side Nav menu just uses a Foundation control anyway, so I can't see it being that difficult for MadCap to provide it as an option for the menu proxy.
minicyclist
Propeller Head
Posts: 60
Joined: Wed Apr 09, 2014 3:51 pm

Re: Add accordion side menu with location highlight, to top

Post by minicyclist »

Thanks all for replies. I'm actually having some success with Smartmenus. I now have a collapsible menu with location expand and highlight, though it hasn't been stress tested.

I needed to do a couple of things:

- Factor in this new behaviour: http://kb.madcapsoftware.com/Content/Mi ... _Menus.htm
- Remove the CSS from the Smartmenus that expands it into a horizontal menu for larger screens

Will post more details if I have it fully working.
minicyclist
Propeller Head
Posts: 60
Joined: Wed Apr 09, 2014 3:51 pm

Re: Add accordion side menu with location highlight, to top

Post by minicyclist »

To summarise my solution, I used Smartmenus as described by Dave Lee in this post:

viewtopic.php?f=9&t=21607

(make sure you keep mc-toc-depth: -1 in the menuproxy or you won't see any dropdowns).

I needed to change the initialise.js script to cope with this behaviour: http://kb.madcapsoftware.com/Content/Mi ... _Menus.htm

And I added a line so that the Smartmenu would open to highlight the current page.

Here's the full initialise.js:

Code: Select all

$(document).ready(function () {
    $(".menu").on("loaded", function () {
        $(function () {
            /* add classes used by smartmenus */
            $('#smartmenu>ul.menu').addClass("sm sm-mint");

            /* remove Flare's "menu" class from menu proxy */
            $('#smartmenu>ul.menu').removeClass("menu");

            /* initialise smartmenus */
            $('#smartmenu>ul.sm').smartmenus({
                markCurrentItem: true,
                markCurrentTree: true,
                keepHighlighted: true,
                keepInViewport: true,
                noMouseOver: true,
                hideOnClick: false, 
                collapsibleShowFunction: null
            });
						
           $("#smartmenu>ul.sm").smartmenus("itemActivate",$ ("#smartmenu").find("a.current").eq(-1));
						
		
        });
    });
});
This is working well and I'm planning to roll it out in our docs. Although, I'm still using Smartmenus 1.0.0-beta1, I'd like to upgrade to 1.1.0 as it offers additional functionality for how parent topics are opened. However if I upgrade, everything breaks and I get the following Javascript error in the console:

Code: Select all

Uncaught Error: Mismatched anonymous define() module: function($) {

	var menuTrees = [],
		mouse = false, // optimize for touch by default - we will detect for mouse input
		touchEvents = 'ontouchstart' in window, // we use this just to choose between toucn and pointer events, not for touch screen detection
		mouseDetectionEnabled = false,
		requestAnimationFrame = window.requestAnimationFrame || function(callback) { return setTimeout(callback, 1000 / 60); },
		cancelAnimationFrame = window.cancelAnimationFrame || function(id) { clearTimeout(id); },
		canAnimate = !!$.fn.animate;

	// Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.)
	function initMouseDetection(disable) {
		var eNS = '.smartmenus_mouse';
		if (!mouseDetectionEnabled && !disable) {
			// if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present
			// in practice, this seems like impossible to trick unintentianally with a real mouse and a pretty safe detection on touch devices (even with older browsers that do not support touch events)
			var firstTime = true,
				lastMove = null,
				events = {
					'mousemove': function(e) {
						var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() };
						if (lastMove) {
							var deltaX = Math.abs(lastMove.x - thisMove.x),
								deltaY = Math.abs(lastMove.y - thisMove.y);
		 					if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) {
								mouse = true;
								// if this is the first check after page load, check if we are not over some item by chance and call the mouseenter handler if yes
								if (firstTime) {
									var $a = $(e.target).closest('a');
									if ($a.is('a')) {
										$.each(menuTrees, function() {
											if ($.contains(this.$root[0], $a[0])) {
												this.itemEnter({ currentTarget: $a[0] });
												return false;
											}
										});
									}
									firstTime = false;
								}
							}
						}
						lastMove = thisMove;
					}
				};
			events[touchEvents ? 'touchstart' : 'pointerover pointermove pointerout MSPointerOver MSPointerMove MSPointerOut'] = function(e) {
				if (isTouchEvent(e.originalEvent)) {
					mouse = false;
				}
			};
			$(document).on(getEventsNS(events, eNS));
			mouseDetectionEnabled = true;
		} else if (mouseDetectionEnabled && disable) {
			$(document).off(eNS);
			mouseDetectionEnabled = false;
		}
	}

	function isTouchEvent(e) {
		return !/^(4|mouse)$/.test(e.pointerType);
	}

	// returns a jQuery on() ready object
	function getEventsNS(events, eNS) {
		if (!eNS) {
			eNS = '';
		}
		var eventsNS = {};
		for (var i in events) {
			eventsNS[i.split(' ').join(eNS + ' ') + eNS] = events[i];
		}
		return eventsNS;
	}

	$.SmartMenus = function(elm, options) {
		this.$root = $(elm);
		this.opts = options;
		this.rootId = ''; // internal
		this.accessIdPrefix = '';
		this.$subArrow = null;
		this.activatedItems = []; // stores last activated A's for each level
		this.visibleSubMenus = []; // stores visible sub menus UL's (might be in no particular order)
		this.showTimeout = 0;
		this.hideTimeout = 0;
		this.scrollTimeout = 0;
		this.clickActivated = false;
		this.focusActivated = false;
		this.zIndexInc = 0;
		this.idInc = 0;
		this.$firstLink = null; // we'll use these for some tests
		this.$firstSub = null; // at runtime so we'll cache them
		this.disabled = false;
		this.$disableOverlay = null;
		this.$touchScrollingSub = null;
		this.cssTransforms3d = 'perspective' in elm.style || 'webkitPerspective' in elm.style;
		this.wasCollapsible = false;
		this.init();
	};

	$.extend($.SmartMenus, {
		hideAll: function() {
			$.each(menuTrees, function() {
				this.menuHideAll();
			});
		},
		destroy: function() {
			while (menuTrees.length) {
				menuTrees[0].destroy();
			}
			initMouseDetection(true);
		},
		prototype: {
			init: function(refresh) {
				var self = this;

				if (!refresh) {
					menuTrees.push(this);

					this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, '');
					this.accessIdPrefix = 'sm-' + this.rootId + '-';

					if (this.$root.hasClass('sm-rtl')) {
						this.opts.rightToLeftSubMenus = true;
					}

					// init root (main menu)
					var eNS = '.smartmenus';
					this.$root
						.data('smartmenus', this)
						.attr('data-smartmenus-id', this.rootId)
						.dataSM('level', 1)
						.on(getEventsNS({
							'mouseover focusin': $.proxy(this.rootOver, this),
							'mouseout focusout': $.proxy(this.rootOut, this),
							'keydown': $.proxy(this.rootKeyDown, this)
						}, eNS))
						.on(getEventsNS({
							'mouseenter': $.proxy(this.itemEnter, this),
							'mouseleave': $.proxy(this.itemLeave, this),
							'mousedown': $.proxy(this.itemDown, this),
							'focus': $.proxy(this.itemFocus, this),
							'blur': $.proxy(this.itemBlur, this),
							'click': $.proxy(this.itemClick, this)
						}, eNS), 'a');

		require.min.js:13)
    at L (require.min.js:41)
    at Object.g [as require] (require.min.js:104)
    at requirejs (require.min.js:126)
    at MadCap.WebHelp.HelpSystem.LoadBreakpoints (MadCapAll.js:57)
    at MadCap.WebHelp.HelpSystem.<anonymous> (MadCapAll.js:57)
    at HTMLScriptElement.i (MadCapAll.js:29)
    at HTMLScriptElement.dispatch (jquery.min.js:3)
    at HTMLScriptElement.y.handle (jquery.min.js:3)
So for now I'm stuck with 1.0.0.

It's a shame Madcap don't include more common web components out of the box; a collapsible side menu like this should really come with it.

Happy that we now have a solution but grateful if anyone can help me with the above error so we have an upgrade path.
kathryngz
Propeller Head
Posts: 76
Joined: Wed May 14, 2014 11:31 am

Re: Add accordion side menu with location highlight, to top nav

Post by kathryngz »

I realize I'm posting some years after the initial post, but I was able to get rid of that error by moving the reference to initialise.js to the end of the template page, just before the closing body tag. I also included defer:

<script type="text/javascript" defer="defer" src="../smartmenus-1.2.1/initialise.js">
</script>

I didn't test without defer, though, so I don't know if that made a difference.

Hope that is helpful to someone.
Post Reply