Try our conversational search powered by Generative AI!

Avoid hiding navigation menu when changing between sites?


Hi there, 
I've noticed that showing the navigation pane in the left side and even when pinning it too, gets hidden again when changing between sites. Is there a way to avoid that by saving and persisting pane(s)? to users last choice?.  Can I do it with C# or javascript code - or configuration in some config file?
Thanks in advance and best regards, 

Jun 05, 2023 22:32


I was just having a look at MenuPin to see how it was done in there.

From the code I can see they are loading the users profile and when the button is clicked they pin the menu based on a key.

You could write something that will do this automatically and possibly even store this for future logins / loads.

I had thought that the CMS UI was clever to know this at one point i could be wrong however, another was wether you had all properties / ope view enabled also.



Jun 06, 2023 10:41

Thanks for the initial input and thoughts Paul!
Can you write a sketch of what actions / bullets I should go through to create and include the right files and somewhat what changes that is necessary to possibly make that desired change?
E.g. should the should the referenced js file in your link somehow be used?

Thanks in advance and best regards,

Jun 06, 2023 15:36

Hi Soren,

Here is some steps I would take:

  1. Clone the repo and add to a demo alloy project (FYI this is CMS 11).
  2. Ensure the menu pin functionality is working as expected.
  3. Rename name 'Menupin' to 'TreeNavigationPin', you will need to go through the solution and ensure all areas neccessary are changed, even the assemblies and csproj names, etc.
  4. Ensure the menu pin functionality is working as expected are changing.
  5. Find out the menu object you need to interact with, in MenuPin it is 'globalMenu'. if you log this to console or debug the js you might be able to find this easier.
  6. Switch out globalMenu for navigationMenu.
  7. Test and see if it works.

Once it is all working look at migrating/upgrading to CMS12.

This is all to be taken with a pinch of salt. And you will most likely encounter issues so accomodate for these along the way.


Jun 07, 2023 9:07

Thanks a lot for your answer and thoughts Paul.
After reiewing the code to clone, eventually upgrade and maintain in the future, I decided to make a smaller and standard plain javascript to do the job. I know this is "flying hack" on top of the standard framework to consider, if they change it, but I would assume maintaining the cloned code to be much worse if it gets out of sync with the native solution.

What I did was adding this plain pinNavigationMenu.js file handling both navigation on the left and assets menu on the right:

window.onload = function () {

    //This purpose of this DOM manipulation is to invert the default
    //behavior of the left side navigation menu and the right side
    //assets menu so they are present by default and only hidden if
    //the user chooses it.
    var navigationPinMenuBtnId = "dijit_form_ToggleButton_7";
    var navigationMenuBtnId = "uniqName_61_76";
    var navigationSessionCookieName = "unPinNavigationMenu";
    var assetsPinMenuBtnId = "dijit_form_ToggleButton_11";
    var assetsMenuBtnId = "uniqName_61_79";
    var assetsSessionCookieName = "unPinAssetsMenu";

    //wait until element exists in DOM using the MutationObserver api.
    function waitForElm(id) {
        return new Promise(resolve => {
            if (document.getElementById(id)) {
                return resolve(document.getElementById(id));

            const observer = new MutationObserver(mutations => {
                if (document.getElementById(id)) {

            observer.observe(document.body, {
                childList: true,
                subtree: true

    // save to cookie. By default, the cookie is deleted when the browser is closed
    var setSessionCookie = function (name, value) {
        document.cookie = name + "=" + (value || "") + "; path=/";
    // read cookie by name.
    function getSessionCookie(cname) {
        let name = cname + "=";
        let decodedCookie = decodeURIComponent(document.cookie);
        let ca = decodedCookie.split(";");
        for (let i = 0; i < ca.length; i++) {
            let c = ca[i];
            while (c.charAt(0) == " ") {
                c = c.substring(1);
            if (c.indexOf(name) == 0) {
                return c.substring(name.length, c.length);
        return "";

    // navigation event Handler
    function navigationClickHandler() {
        clickHandler(navigationPinMenuBtnId, navigationMenuBtnId, navigationSessionCookieName)

    // assets event Handler
    function assetsClickHandler() {
        clickHandler(assetsPinMenuBtnId, assetsMenuBtnId, assetsSessionCookieName)

    function clickHandler(pinBtnId, menuBtnId, unPinSessionCookieName) {
        let menuBtn = document.getElementById(menuBtnId);
        let menuPinBtn = document.getElementById(pinBtnId);
        //menu is open and being closed by unpinning. Save that to cookie.
        if (menuBtn != null && menuBtn.getAttribute("aria-pressed") == "true" &&
            menuPinBtn != null && menuPinBtn.getAttribute("aria-pressed") == "true") {
            setSessionCookie(unPinSessionCookieName, true);
        else {
            setSessionCookie(unPinSessionCookieName, false);

    function bindMenuButton(menuPinBtn, clickHandler) {
        let pinMenuClickBound = false;
        if (window.location.href.indexOf("EPiServer/CMS") > 0 && pinMenuClickBound == false && menuPinBtn != null) {
                // Bind click event
                menuPinBtn.addEventListener("click", clickHandler);
                    pinMenuClickBound = true;

    function showMenu(unPinSessionCookieName, menuBtnId, menuPinBtn) {
        let menuBtn = document.getElementById(menuBtnId);
        if (window.location.href.indexOf("EPiServer/CMS") > 0 &&
            menuBtn != null && menuPinBtn != null) {
            //click to close if cookie says so -
            //or click to show if closed just by default
            if ((getSessionCookie(unPinSessionCookieName) == "true" &&
                menuPinBtn.getAttribute("aria-pressed") == "true" &&
                menuBtn.getAttribute("aria-pressed") == "true") ||
                menuPinBtn.getAttribute("aria-pressed") == "false" &&
                getSessionCookie(unPinSessionCookieName) == "") {

    //elements are not in DOM after initial page load, so wait for them to be present.
    waitForElm(navigationPinMenuBtnId).then((btn) => {
        bindMenuButton(btn, navigationClickHandler);
        showMenu(navigationSessionCookieName, navigationMenuBtnId, btn);
    waitForElm(assetsPinMenuBtnId).then((btn) => {
        bindMenuButton(btn, assetsClickHandler);
        showMenu(assetsSessionCookieName, assetsMenuBtnId, btn);

and then this module.config file in the root of the website project:

        <add name="epi-cms.widgets.base" path="~/ClientResources\PinNavigationMenu\pinNavigationMenu.js" resourceType="Script" />

Edited, Jun 08, 2023 7:40

Hi Soren,

Glad you got it sorted.



Jun 08, 2023 12:04
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.