kenneth_rogers
Instructure Alumni
Instructure Alumni

Help With Custom Menu Icons and Script

Jump to solution


Hello, community. I am hoping you can provide me with some assistance as I pose these series of questions. Thanks so much!

First, a little background...

course_menu.jpg

We utilize some code (I believe generously borrowed from  @kenneth_larsen ​) to add a few menu items to our menu in Canvas. Because we support a district of five individual colleges in our instance, these items need to remain in our menu and cannot be moved to the updated Help Menu. Also, we previously decided to not include any icons with these items (see graphic to the right).

With the update to the course menu and it now being collapsible (see https://community.canvaslms.com/docs/DOC-8403#jive_content_id_Global_Navigation​ within Canvas Production Release Notes (2016-10-29)), we have now realized that the text is removed (makes sense), so we must have icons present.

Here's probably the biggest problem - I can read through javascript, steal some people's code (thanks, guys!), and basically understand what's going on - but sometimes you just need to wave the white flag and ask for help!

I have gone through several pages and sites, but I still need assistance with adding an image (I presume svg) as my icon.

I have modified our current javascript file to add an icon from the style sheet - this works, but the icon is removed with the text when you collapse the menu.

I found  @jblumberg ​'s post on Has anyone been working on scripts for the new Beta UI? (his code can be found here) - and while this utilizes a svg image, but it creates a popup window. Although, in reading his notes, it says it is generalized so it can create items with or without the modal window.

So - the questions - does someone have a javascript fix (or js and css fix even) to add custom menu items, including an icon, that won't vanish when the menu collapses? Or is there a way to add svg icons with  @kenneth_larsen ​'s code? What about modifying  @jblumberg ​'s code to add three individual items instead of one item and a popup window?

Help?

1 Solution
kenneth_larsen
Community Champion

Updated to include parameter to open in a new tab.

Okay, let's see how well this works. I changed the original code in the following ways:

  1. Added some CSS so the icon is a closer match in size to the other icons
  2. You can pass an icon class into the function or any other HTML including images

Sadly, in order for the icon to not disappear, it had to be added above the text like the other links which makes it take up more vertical space (if this is an issue, let me know).

Here is the new function:

    var styleAdded = false; 

    function addMenuItem(linkText, linkhref, icon, target) { 

        var iconHtml = '', 

            itemHtml,

            linkId = linkText.split(' ').join('_'), 

            iconCSS = '<style type="text/css">' + 

                '   i.custom_menu_list_icon:before {' + 

                '       font-size: 27px;' + 

                '       width: 27px;' + 

                '       line-height: 27px;' + 

                '   }' + 

                '   i.custom_menu_list_icon {' + 

                '       width: 27px;' + 

                '       height: 27px;' + 

                '   }' + 

                '   body.primary-nav-expanded .menu-item__text.custom-menu-item__text {' + 

                '       white-space: normal;' + 

                '       padding: 0 2px;' + 

                '   }' + 

                '</style>'; 

        if (icon !== '') { 

            // If it is a Canvas icon 

            if (icon.indexOf('icon') === 0) { 

                iconHtml = '<div class="menu-item-icon-container" role="presentation"><i class="' + icon + ' custom_menu_list_icon"></i></div>'; 

            // for an svg or other image 

            } else if (icon !== '') { 

                iconHtml = '<div class="menu-item-icon-container" role="presentation">' + icon + '</div>'; 

            } 

        }

        // Process Target

        if (target !== undefined && target !== null && target !== '') {

            target = ' target="' + target + '"';

        } else {

            target = '';

        }

        // Build item html 

        itemHtml = '<li class="ic-app-header__menu-list-item ">' + 

                '   <a id="global_nav_' + linkId + '" href="' + linkhref + '" class="ic-app-header__menu-list-link" ' + target + '>' + iconHtml + 

                '       <div class="menu-item__text custom-menu-item__text">' + linkText + '</div>' + 

                '   </a>' + 

                '</li>'; 

        $('#menu').append(itemHtml); 

        // Add some custom css to the head the first time 

        if (!styleAdded) { 

            $('head').append(iconCSS); 

            styleAdded = true; 

        } 

    }

Adding items is similar to before.

1. Add an item without an icon:

addMenuItem('No Icon', 'desired_url', '');

     I tried making it so the text was visible if no icon was selected but even just "Support" was to long to fit in the menu area.

2. Add an item with a Canvas icon class:

addMenuItem('Library', 'desired_url', 'icon-educators');

3. Add an item with an SVG or image. Instead of the class, put in the HTML you want in the icon area, the example below is the SVG Canvas uses for the life preserver:

addMenuItem('Student Support', 'desired_url', '<svg xmlns="http://www.w3.org/2000/svg" class="ic-icon-svg menu-item__icon svg-icon-lifepreserver" version="1.1" x="0" y="0" viewBox="0 0 200 200" enable-background="new 0 0 200 200" xml:space="preserve" fill="currentColor"><path d="M190 80h-2.3C180 46.4 153.6 20 120 12.3V10c0-5.5-4.5-10-10-10H90c-5.5 0-10 4.5-10 10v2.3C46.4 20 20 46.4 12.3 80H10C4.5 80 0 84.5 0 90v20c0 5.5 4.5 10 10 10h2.3c7.7 33.6 34.1 60 67.7 67.7v2.3c0 5.5 4.5 10 10 10h20c5.5 0 10-4.5 10-10v-2.3c33.6-7.7 60-34.1 67.7-67.7h2.3c5.5 0 10-4.5 10-10V90C200 84.5 195.5 80 190 80zM167.1 80h-32.6c-3.5-6-8.4-10.9-14.4-14.4V32.9C142.5 39.7 160.3 57.5 167.1 80zM100 120c-11 0-20-9-20-20s9-20 20-20c11 0 20 9 20 20S111 120 100 120zM80 32.9v32.6C74 69.1 69.1 74 65.6 80H32.9C39.7 57.5 57.5 39.7 80 32.9zM32.9 120h32.6c3.5 6 8.4 10.9 14.4 14.4v32.6C57.5 160.3 39.7 142.5 32.9 120zM120 167.1v-32.6c6-3.5 10.9-8.4 14.4-14.4h32.6C160.3 142.5 142.5 160.3 120 167.1z"></path></svg>');

If you want to have the links open in a new tab, add a fourth parameter of '_blank' (or any other valid html target value). Example:

addMenuItem('Library', 'desired_url', 'icon-educators', '_blank');

Here is what those would look like with the Help item for reference (note option 1 doesn't appear when the menu is collapsed).

Expanded MenuCollapsed Menu
Screen Shot 2016-10-27 at 3.48.16 PM.pngScreen Shot 2016-10-27 at 3.48.23 PM.png

Let me know if you have questions.

Good luck!

View solution in original post

65 Replies
estradak
Community Member

Where would I load our script?  My new CMS is not wanting to help and I am hoping to get an attendance icon loaded to make my life a little easier.

Morning,  @estradak ‌! I'm trying to find a guide for you, but you load it in the themes area of the admin portion. In the theme you are using, you have an area to upload either a CSS or a java file, and you would upload this as a .js file.

Excellent! Thanks for doing the legwork, stefaniesanders‌!!

Thanks a bunch!

Thank you.

dloomis
Community Participant

Thanks to everyone for providing code and instructions for adding custom links/icons. I was able to get it to work but now need to hide one icon from students - has anyone done this and have code they would share? Thanks!

Hi dloomis,

The following should help. It is used in conjunction with the addMenuItem function described above. It is a little longer than just adding a new link but it will check the user's roles and add the link if needed.

// Define what roles should see the link
var showToRoles = [
        'root_admin',
        'admin',
        'teacher'
    ],
    addLink = false;
// Make sure the Canvas user roles variable exists
if (ENV.current_user_roles !== undefined) {
    // Loop through your allowed roles to see if the user has that role
    $.each(showToRoles, function (index, val) {
        // If the user has the role, mark that the link needs to be added
        if ($.inArray(val, showToRoles) > -1) {
            addLink = true;
        }
    });
    // add the link as needed
    if (addLink) {
        addMenuItem('Library', 'desired_url', 'icon-educators', '_blank');
    }
}
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

A simpler way would be to just see if they are a student, however some teachers, administrators, designers, etc. may also be students (even if just in a sandbox course) and just checking to see if they are a student may hide it from some users that you would want to see it. Line 19 above would be whatever parameters you need for the link. You could also include multiple addMenuItem() calls if you had multiple links that you only want to show to that role list.

Thanks so much!

JACOBSEN_C
Community Contributor

What's the trick to get two custom options to show in the global navigation column?  Does code need to be added to both the CSS and JS file?

0 Kudos

We just added to the .js file. See my example above!

Hi Clint,

The line that actually does the magic and adds the item to the global nav column is 

addMenuItem('Library', 'desired_url', 'icon-educators', '_blank');

So if you want to add an additional menu item to the global nav you just need to add an additional call to the addMenuItem javascript function.

garrett_william
Community Participant

Hey everyone! I have successfully implemented the menu customization in my test instance. I was able to use the provided JS code and Instructure icons to make the desired modifications. 

Custom Icons

Unfortunately, I was not able to get this to work with the custom SVG icons I created. I was hoping somebody could help me. I would like to replace the Instructure icons with these three custom icons for the menu items below:

Web 2.0:

https://uclor.ucps.k12.nc.us/UCVirtual/Canvas/webmagic.svg

Tutorials:

https://uclor.ucps.k12.nc.us/UCVirtual/Canvas/tutorials2.svg

UCV Honorees:

https://uclor.ucps.k12.nc.us/UCVirtual/Canvas/ucvaward2.svg

I tried to follow the suggestions posted here but have so far come up short.

My current JS code reads like this:

}
var styleAdded = false; 
    function addMenuItem(linkText, linkhref, icon, target) {
        var iconHtml = '', 
            itemHtml, 
            linkId = linkText.split(' ').join('_'), 
            iconCSS = '<style type="text/css">' + 
                '   i.custom_menu_list_icon:before {' + 
                '       font-size: 27px;' + 
                '       width: 27px;' + 
                '       line-height: 27px;' + 
                '   }' + 
                '   i.custom_menu_list_icon {' + 
                '       width: 27px;' + 
                '       height: 27px;' + 
                '   }' + 
                '   body.primary-nav-expanded .menu-item__text.custom-menu-item__text {' + 
                '       white-space: normal;' + 
                '       padding: 0 2px;' + 
                '   }' + 
                '</style>'; 
        if (icon !== '') { 
            // If it is a Canvas icon 
            if (icon.indexOf('icon') === 0) { 
                iconHtml = '<div class="menu-item-icon-container" role="presentation"><i class="' + icon + ' custom_menu_list_icon"></i></div>'; 
            // for an svg or other image 
            } else if (icon !== '') { 
                iconHtml = '<div class="menu-item-icon-container" role="presentation">' + icon + '</div>'; 
            } 
        } 
        // Build item html 
        itemHtml = '<li class="ic-app-header__menu-list-item ">' + 
                '   <a id="global_nav_' + linkId + '" href="' + linkhref + '" class="ic-app-header__menu-list-link">' + iconHtml + 
                '       <div class="menu-item__text custom-menu-item__text">' + linkText + '</div>' + 
                '   </a>' + 
                '</li>'; 
        $('#menu .ic-app-header__menu-list-item').last().before(itemHtml); 
        // Add some custom css to the head the first time 
        if (!styleAdded) { 
            $('head').append(iconCSS); 
            styleAdded = true; 
        } 
           
    }
$(document).ready(function() { 
addMenuItem('Web 2.0','https://sites.google.com/a/ucps.k12.nc.us/ucv-student-launch/ucv-canvas-launch', 'icon-keyboard-shortcuts', '_blank');
addMenuItem('Tutorials','https://docs.google.com/document/d/1mcokUC9_dJARCjKNv-gTxysZqBAR9iYTc_4ffS25rUc/edit#heading=h.xk1vs...', 'icon-educators', '_blank');
addMenuItem('UCV Honorees','https://www.ucps.k12.nc.us/Page/6247', 'icon-star-light', '_blank');
}); ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Thanks to anyone who is able to help me make these changes : )

Pass the svg image into the addMenuItem function instead of an icon class:

addMenuItem('Web 2.0','https://sites.google.com/a/ucps.k12.nc.us/ucv-student-launch/ucv-canvas-launch', '<img src="https://uclor.ucps.k12.nc.us/UCVirtual/Canvas/webmagic.svg">', '_blank');

You will need to use CSS to customize the svg once it is in the sidebar.

Thank you so much! I'm going to give it a try. I'll let you know if I need help with the CSS. I've read what others have tried and will go from there : )

Kenneth I want you and the community to know that your suggestions worked! I cannot thank you enough.

Unfortunately, I am stuck on the CSS customizations. Once again, I am out of my depth. I plan on changing the custom  SVG icons I created to white (instead of black) to get the colors right for my instance. I am unsure what I need to do for the sizing of the icons so that they are more in keeping with the default Canvas menu icons (Admin, Dashboard, etc). 

Any help would be great. I know I am asking and taking a lot here. Fingers crossed someone can help me cross the finish line.

I'll share my final results and code once I get it the way it needs to be : )

Try adding the same ic-icon-svg CSS class that Canvas uses on their icons in the sidebar, that might take care of color and resizing for you.

That would look something like this in your code:

$(document).ready(function() {
    addMenuItem('Web 2.0','https://sites.google.com/a/ucps.k12.nc.us/ucv-student-launch/ucv-canvas-launch', '<img class="ic-icon-svg" src="https://uclor.ucps.k12.nc.us/UCVirtual/Canvas/webmagic.svg">', '_blank');
    addMenuItem('Tutorials','https://docs.google.com/document/d/1mcokUC9_dJARCjKNv-gTxysZqBAR9iYTc_4ffS25rUc/edit#heading=h.xk1vs...', '<img class="ic-icon-svg" src="https://uclor.ucps.k12.nc.us/UCVirtual/Canvas/tutorials2.svg">', '_blank');
    addMenuItem('UCV Honorees','https://www.ucps.k12.nc.us/Page/6247', '<img class="ic-icon-svg" src="https://uclor.ucps.k12.nc.us/UCVirtual/Canvas/ucvaward2.svg">', '_blank');
});‍‍‍‍‍‍‍‍‍‍

If you are curious, this is the CSS associated with that class in Canvas:

.ic-app-header__menu-list-link .ic-icon-svg {
    width: 26px;
    display: inline-block;
    vertical-align: middle;
    fill: var(--ic-brand-global-nav-ic-icon-svg-fill);
}‍‍‍‍‍‍

Kenneth this totally did the trick! You are AWESOME! Thank you so much for the help. Little by little I am picking up on the CSS and JS coding skills. Many of them have come directly from you!

I have a little more graphic design work to do. I plan on using Adobe Illustrator to adjust the SVG paths (image tracing/ outline) to better match the outline width of the default Canvas icons. The discrepancy is most noticeable on the Web 2.0 icon. I'll update my Menu image once I get the icons just right : )

Here is the resulting Menu:

285408_Screen Shot 2018-08-13 at 1.26.11 PM.png

Here is the final code in full:

}
var styleAdded = false; 
    function addMenuItem(linkText, linkhref, icon, target) {
        var iconHtml = '', 
            itemHtml, 
            linkId = linkText.split(' ').join('_'), 
            iconCSS = '<style type="text/css">' + 
                '   i.custom_menu_list_icon:before {' + 
                '       font-size: 27px;' + 
                '       width: 27px;' + 
                '       line-height: 27px;' + 
                '   }' + 
                '   i.custom_menu_list_icon {' + 
                '       width: 27px;' + 
                '       height: 27px;' + 
                '   }' + 
                '   body.primary-nav-expanded .menu-item__text.custom-menu-item__text {' + 
                '       white-space: normal;' + 
                '       padding: 0 2px;' + 
                '   }' + 
                '</style>'; 
        if (icon !== '') { 
            // If it is a Canvas icon 
            if (icon.indexOf('icon') === 0) { 
                iconHtml = '<div class="menu-item-icon-container" role="presentation"><i class="' + icon + ' custom_menu_list_icon"></i></div>'; 
            // for an svg or other image 
            } else if (icon !== '') { 
                iconHtml = '<div class="menu-item-icon-container" role="presentation">' + icon + '</div>'; 
            } 
        } 
        // Build item html 
        itemHtml = '<li class="ic-app-header__menu-list-item ">' + 
                '   <a id="global_nav_' + linkId + '" href="' + linkhref + '" class="ic-app-header__menu-list-link">' + iconHtml + 
                '       <div class="menu-item__text custom-menu-item__text">' + linkText + '</div>' + 
                '   </a>' + 
                '</li>'; 
        $('#menu .ic-app-header__menu-list-item').last().before(itemHtml); 
        // Add some custom css to the head the first time 
        if (!styleAdded) { 
            $('head').append(iconCSS); 
            styleAdded = true; 
        } 
           
    }
$(document).ready(function() {
    addMenuItem('Web 2.0','https://sites.google.com/a/ucps.k12.nc.us/ucv-student-launch/ucv-canvas-launch', '<img class="ic-icon-svg" src="https://uclor.ucps.k12.nc.us/UCVirtual/Canvas/magicwebCSS.svg">', '_blank');
    addMenuItem('Tutorials','https://docs.google.com/document/d/1mcokUC9_dJARCjKNv-gTxysZqBAR9iYTc_4ffS25rUc/edit#heading=h.xk1vs...', '<img class="ic-icon-svg" src="https://uclor.ucps.k12.nc.us/UCVirtual/Canvas/tutorialCSS.svg">', '_blank');
    addMenuItem('Honorees','https://www.ucps.k12.nc.us/Page/6247', '<img class="ic-icon-svg" src="https://uclor.ucps.k12.nc.us/UCVirtual/Canvas/ucvawardCSS.svg">', '_blank');
});
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

THANK YOU SO MUCH! this community, as always, is awesome!

qnguyen
Community Contributor

Hi,

Does anyone have the link for all the Canvas Icon that I can use and has the big size as for Global Navigation. I used one from a list but looks way smaller than others ( the one is circle) Thanks

344186_pastedImage_1.png

0 Kudos
dschuma
Community Participant

Thank you everyone for the great contributions.  I found that this solution does not work on a phone browser (I haven't yet reviewing how to implement in the apps).  The global nav window is a flyout created by JS that is loaded when the hamburger icon is clicked.  Does anyone have a solution for this situation or even one for the mobile apps?  My current strategy is to start a timer when the hamburger is clicked testing for the existence of the menu list.  I'd like input before I head down that path.

nwilson7
Community Champion

@kenneth_larsen Do the pop-out menu options still work?  I pasted in the samples and it does not do anything other than add the icon to the menu.  My end goal is to have a button that pop-out with all the tools students use.  Eventually I would love it to pass the authentication but that is way out of my knowledge base.  We use SAML with Auth0 so it seems possible.  

Thanks!!!

0 Kudos

We actually stopped using this feature at USU after Canvas added in the ability to customize the help section so I'm probably not the best one to ask. That being said, In my work with Cidi Labs, I see a lot of institutions JavaScript files and it seems like I have recently seen a custom popout sidebar being used in Canvas. Sadly, I don't remember who it was that was using it. Hopefully, some of the others who have used this script can chime in.

0 Kudos

Thanks @kenneth_larsen for your reply.  Also really enjoying CidiLabs, it has added many missing features to course building!

0 Kudos
chriscas
Community Coach
Community Coach

We use the menu with popout tray from CCSD/Robert Carrol and have really had no major issues with it in the last couple years.  As always with custom scripting, Instructure could make a change to Canvas at anytime that would break the code, but hopefully those situations will be very rare.  Based on our experience, I'd recommend anyone interested in adding custom menus check it out!

0 Kudos

Thanks @chriscas , I will check these out!

0 Kudos
zowada-a
Community Participant

Hi all, I've got a question - I've tried a lot of what I've seen in this thread, but I am not getting things to work.

What I am trying to do is add an icon over the linked text in the sidebar.

Here is what I have for the AddMenuItem call:

addMenuItem('Navigate', 'https://uwyo.navigate.eab.com/app/#/authentication/remote/', '<img src="https://uwyo.navigate.eab.com/app/resources/logo/navigate/navigate.svg">','_blank');

However, in my sidebar, there's no picture and it just has "> in front of the word Navigate, so I think it's ignoring my picture entirely.  I tried this with .png and .ico formats too (different location), but nothing.

Any ideas on why this isn't working? I appreciate any ideas.

Thanks!
Sam

0 Kudos