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
kschneider25
Community Champion

Please help us Canvas Developer's Group.

kenneth_larsen
Community Champion

I am just running out the door for lunch but I will take a look at it when I return Smiley Wink

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!

I guess I should also add the standard "Custom JavaScript is not supported by Canvas and is used at your own risk" disclaimer.

Thanks for the warning. But hey - if we can't try to break it, then what's the fun?!

Code looks great. I'll test it in a bit on my end. I genuinely appreciate your input on this.

I'll keep ya posted.

Greetings Kenneth,

We had been using the .js override for a custom popout menu which recently broke. This particular override really suited our needs. The "customize popout help menu" does not work for us. We are a Tier 1 client and already have 7 links on that popout menu. Adding 3 more creates a mess.

Given that situation we feel that this particular button may work for our needs. In our CSS, we also have code for USU Design Tools and CIDILABS design tools, I am pasting the below code below the CSS for those two items and them updating the override and the button is not appearing. I will also attach our full CSS override. Could you perhaps provide direction as to what I am doing wrong?

  var styleAdded = false;   

    function addMenuItem('Catalog and Certificates', 'http://myescu.net/#/' , 'student-view', '_blank') {   

        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;   

        }   

    } 

Hi  @ndragisic ​,

In my first glance at your code, two things stick out.

  1. This code goes in your global JavaScript file not your CSS file.
  2. Line 02 (as pasted above) is defining a JavaScript function and variable names for the information that will be passed into the function. It should read:

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

    After this function is defined you can call this function as many times as you need and pass in different values. To do this (based on what you had entered on line 2) you would add the following after the final } on line 48:

        addMenuItem('Catalog and Certificates', 'http://myescu.net/#/', 'student-view', '_blank');

    You can then duplicate that line as many times as needed with different values. That being said, the third value should represent the icon that you would like displayed. That can include a Canvas icon class or the html for an image.

If that doesn't resolve the problem, let me know and I will dig a little deeper.

Thank you I will try this now!

Okay, This is what I have now:

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;   

        }   

    } 

        addMenuItem('Catalog', 'http://myescu.net/#/', 'materials-required-light', '_blank');

        addMenuItem('My Sessions and Certificates', 'https://myescu.net/#/user_session', 'student-view', '_blank');

When I apply the attached JS override it does not give me buttons and it breaks my CIDILABS design tools. Any ideas? Seems like they are coming in conflict. I have attached the .js override.

The error is taking place in the code for the custom slide out tray (between the Design Tools code and the code we are discussing). Let me hunt down the original code for that and I will see if I can figure out what is going wrong.

Are you even using the custom slide out menu? It looks like you are missing some of the code which would prevent it from working. The question is, do you want me to fix it so the custom slide out code works or just remove it?

I would like the custom slide out to work so I do not have to redo the graphics on all the instructions referring to it. I was just taking what I could get and trying not to be fussy. This is what it used to look like before it broke:

SessionsAndCertificates.png

This is my code which used to work:

$(document).ready(function() {

var trayLinks = [

{key: 'http://myescu.net/', val: 'Catalog</br></br>'},

{key: 'http://myescu.net/#/user_session', val: 'My Sessions & Certificates</br></br>'},

{key: 'https://www.escweb.net/tx_r18/', val: 'ESC 18 Legacy Catalog and Certificates</br></br>'},

];

var slide_out_title = "Catalog and Certificates"; //Changes the title on the slide out menu

var global_nav_name = "Catalog and Certificates"; //Change the title on the global navigation menu

var footerContent = 'Region 18 legacy users should use legacy catalog to register for or download certificates for past courses.'; //Changes the text of the bottom on the slide out tray

This is what it looks like now:

Broken.PNG

I am not sure why it stopped working, but I have been fussing with it for weeks.

So, just to clarify, is the core issue that you are trying to solve the missing icon (square) above Catalog and Certificates?

If so, that is a result of the update Canvas made to their icons on January 9th (or there about). To fix this, you need to change the content value in the CSS that goes along with the slide out panel. The original GitHub CSS had:

.icon-resources:before {

  content: "\f13c";

}

Based on your screenshot, you were using an icon that doesn't have a match in the new icon set. The following is the closest I could find.

.icon-resources:before {

  content: "\EA2F";

}

If that is not what you are trying to solve, we can go back to fixing your code.

 @kenneth_larsen ‌

Can you tell me where I can find the code for the icons? I'm looking for "\EA2F";  whcih corresponds to the different icons available in the style guide.

The following is the closest I could find.

  1. .icon-resources:before {  
  2.   content"\EA2F";  
  3. }  
JACOBSEN_C
Community Contributor

You bet.  Though... the actual icon that shows is usually + or - 1 or 2 to what's on this page; I dont yet know why - but also haven't asked.

http://instructure.github.io/instructure-icons/#demos/fonts/InstructureIcons-Line.html 

 @JACOBSEN_C is right, the icons are off.  I was actually able to figured out (at least part of) why the icons are off. Some of the icons they list don't actually exist.

For example, the image below suggests that there is a move-left and move-right icon. However, they do not exist in the code so move-up-top is actually EA7B and everything afterwards is thrown off by two. This happens multiple times so the further down the list you go, the more some of the icons are off.

Example icons from Canvas

I usually will put in what is listed then make adjustments based on which icon was actually returned. Not an exact science but it works for now. The danger is if Canvas actually puts in the missing icons and everything is thrown off again. 

The best route is to actually use the Canvas class whenever possible (icon-move-up-top) rather than setting it in CSS using the content code (EA7B). That way, when canvas updates the code, your icon gets updated as well.

As slight modification to  @JACOBSEN_C 's link, you will want to look at the solid variations of the icons rather than the line icons http://instructure.github.io/instructure-icons/#demos/fonts/InstructureIcons-Solid.html 

Good luck! But more importantly, have fun along the way.

Hi  @ndragisic ​,

Based on our conversation outside of the Canvas Community, I have made some adjustments to your JavaScript file so that the slide out panel matches the styling of the other panels in Canvas.

For any others interested, the icon content code was updated in the CSS file as described above and I modified the following lines that come from  @tfullwood ​'s code from:

    var trayHtml = '<div style="position:absolute;background:#fff;" class="ReactTray__Content ReactTray__Content--after-open " tabindex="-1" data-reactid=".' +

  reactId + '.0"><div class="ReactTray__layout" data-reactid=".' +

  reactId + '.0.0"><div class="ReactTray__primary-content" data-reactid=".' +

  reactId + '.0.0.0"><div class="ReactTray__header" data-reactid=".' +

  reactId + '.0.0.0.0"><h1 class="ReactTray__headline" data-reactid=".' +

  reactId + '.0.0.0.0.0">' +

  slide_out_title + '</h1><button class="Button Button--icon-action ReactTray__closeBtn" type="button" data-reactid=".' +

  reactId + '.0.0.0.0.1"><i class="icon-x" data-reactid=".' +

  reactId + '.0.0.0.0.1.0"></i><span class="screenreader-only" data-reactid=".' +

  reactId + '.0.0.0.0.1.1">Close</span></button></div><ul class="ReactTray__link-list" data-reactid=".' +

  reactId + '.0.0.0.1">' +

  displayVals + '</ul></div><div class="ReactTray__secondary-content" data-reactid=".' +

  reactId + '.0.0.1"><div class="ReactTray__info-box" data-reactid=".' +

  reactId + '.0.0.1.0">' +

  footerContent + '</div></div></div></div>' +

  '<script>$(\'.Button.Button--icon-action.ReactTray__closeBtn, .Button.Button--icon-action.ReactTray__closeBtn .icon-x\').click(function () {$(\'.ReactTrayPortal div\').removeAttr(\'style\');$(\'.ReactTrayPortal div\').removeAttr(\'class\');$(\'.ReactTrayPortal div\').html("");$(\'#menu, .menu-item.ic-app-header__menu-list-item a\').removeClass(\'ui-state-disabled\').removeAttr(\'disabled\');$(\'#customTrayOverlay\').hide();$(\'#custom_nav\').css(\'background-color\', \'\');$(\'.icon-resources\').css(\'color\', \'#fff\');});</script>';

To:

    var trayHtml = '<div style="position:absolute;background:#fff;" class="ReactTray__Content ReactTray__Content--after-open " tabindex="-1" data-reactid=".' +

  reactId + '.0"><div class="ic-NavMenu__layout" data-reactid=".' +

  reactId + '.0.0"><div class="ic-NavMenu__primary-content" data-reactid=".' +

  reactId + '.0.0.0"><div class="ic-NavMenu__header" data-reactid=".' +

  reactId + '.0.0.0.0"><h1 class="ic-NavMenu__headline" data-reactid=".' +

  reactId + '.0.0.0.0.0">' +

  slide_out_title + '</h1><button class="Button Button--icon-action ic-NavMenu__closeBtn" type="button" data-reactid=".' +

  reactId + '.0.0.0.0.1"><i class="icon-x" data-reactid=".' +

  reactId + '.0.0.0.0.1.0"></i><span class="screenreader-only" data-reactid=".' +

  reactId + '.0.0.0.0.1.1">Close</span></button></div><ul class="ic-NavMenu__link-list" data-reactid=".' +

  reactId + '.0.0.0.1">' +

  displayVals + '</ul></div><div class="ic-NavMenu__secondary-content" data-reactid=".' +

  reactId + '.0.0.1"><div class="ic-NavMenu__info-box" data-reactid=".' +

  reactId + '.0.0.1.0">' +

  footerContent + '</div></div></div></div>' +

  '<script>$(\'.Button.Button--icon-action.ic-NavMenu__closeBtn, .Button.Button--icon-action.ic-NavMenu__closeBtn .icon-x\').click(function () {$(\'.ReactTrayPortal div\').removeAttr(\'style\');$(\'.ReactTrayPortal div\').removeAttr(\'class\');$(\'.ReactTrayPortal div\').html("");$(\'#menu, .menu-item.ic-app-header__menu-list-item a\').removeClass(\'ui-state-disabled\').removeAttr(\'disabled\');$(\'#customTrayOverlay\').hide();$(\'#custom_nav\').css(\'background-color\', \'\');$(\'.icon-resources\').css(\'color\', \'#fff\');});</script>';

in order to take advantage of the Canvas panel styles. Which, in essence, was replacing all but the first 'ReactTray__' identifier with 'ic-NavMenu__'.

Let me know if that resolves the rest of your concerns.

You are so amazing and wonderful. Thank you. This worked beautifully.

Is there a way to add the custom icon above the standard Help icon on the Global Navigation? The code works beautifully for us but we would like to adjust the placement. 

Hi Felicia,

I used the jQuery selector $('menu li:last') to select the last <li> in the menu object and the jQuery .before() method to insert before it. 

I used an svg from Canvas since I had a lot of trouble trying to figure out sizing other svgs (using source addresses instead of the path tag). I never quite figured out using the height/width and viewBox properties. 

addFollettButton();

function addFollettButton() {
$('#menu li:last').before('<li id="custom_nav" class="menu-item ic-app-header__menu-list-item">' +
   '<a id="global_nav_resources_link" class="ic-app-header__menu-list-link" href="https://humboldt.edu" target="_blank">' +
      '<div class="menu-item-icon-container" aria-hidden="true">' +
          '<svg xmlns="http://www.w3.org/2000/svg" class="ic-icon-svg ic-icon-svg--follet" version="1.1" x="0" y="0"' +
             'viewBox="0 0 46 45" enable-background="new 0 0 46 45" xml:space="preserve">' +
               '<path d="M8.9,21l2.1-2.1l-0.7-0.7l4.8-4.8l-2.1-2.1l-4.8,4.8l-1.1-1.1l4.8-4.8L9.9,' +
                   '8.2L5.1,13l-1.8-1.8l7.9-7.9l7.8,7.8L21,8.9l-8.2-8.2c-0.4-0.4-1-0.7-1.6-0.7c-0.6,' +
                   '0-1.2,0.2-1.6,0.7L0.7,9.5c-0.9,0.9-0.9,2.4,0,3.3L8.9,21 M45.3,32.3L37.1,24L35,26.1l7.8,' +
                   '7.8l-7.9,7.9L33,39.9l4.8-4.8L35.7,33l-4.8,4.8l-1.1-1.1l4.8-4.8l-2.1-2.1l-4.8,4.8L27.1,34L25,' +
                   '36.1l8.3,8.3c0.4,0.4,1,0.7,1.6,0.7c0.6,0,1.2-0.2,1.6-0.7l8.8-8.8C46.2,34.6,46.2,33.2,45.3,32.3 M45,' +
                   '10.4c0-1-0.4-1.9-1.1-2.6l-6.7-6.7C36.5,0.4,35.6,0,34.6,0S32.7,0.4,32,1.1L4.3,28.8c-0.6,0.6-0.9,1.3-1,' +
                   '2.1L0.1,43c-0.1,0.5,0,1.1,0.4,1.5C0.8,44.8,1.2,45,1.6,45c0.1,0,0.3,0,0.4-0.1l12.2-3.2c0.8-0.1,1.5-0.5,' +
                   '2-1L43.9,13C44.6,12.3,45,11.4,45,10.4L45,10.4z M4.1,40.9L6,33.8l5.3,5.3L4.1,40.9L4.1,40.9z M41.8,10.7L14.6,' +
                   '37.8l-7.5-7.5L34.3,3.2c0.2-0.2,0.3-0.2,0.4-0.2c0.1,0,0.3,0,0.4,0.2l6.6,6.6c0.2,0.2,0.2,0.3,0.2,0.4C41.9,10.4,41.9,10.6,41.8,10.7L41.8,10.7z"/>' +
           '</svg>' +
          '</div>' +
        '<div class="menu-item__text"> Follett\nDiscover' +
       '</div>' +
     '</a>' +
   '</li>');
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Hope this helps!

We actually aren't even using this added button currently, but after looking at my code and the rest of this thread, I felt the need to refactor. I am now using a named Instructure icon from their github: (icon-collection)

function addFollettButton() {
   $('#menu li:last').before('<li id="custom_nav" class="menu-item ic-app-header__menu-list-item">' +
     '<a id="global_nav_resources_link" class="ic-app-header__menu-list-link" href="https://humboldt.edu" target="_blank">' +
       '<div class="menu-item-icon-container" role="presentation">' +
         '<i class="icon-collection custom_menu_list_icon"></i>' +
       '</div>' +
       '<div class="menu-item__text custom-menu-item__text"> Follett\nDiscover' +
       '</div>' +
     '</a>' +
   '</li>');
}‍‍‍‍‍‍‍‍‍‍‍

...and just this snippet of the CSS from above to size the icon since this button will will not open a tray:

i.custom_menu_list_icon:before{
  font-size: 27px;
  width: 27px;
  line-height: 27px;
}

Thank you so much! This was exactly what we needed and it worked beautifully. 

Custom Global navigation at St. Mary

JACOBSEN_C
Community Contributor

Is your custom option still working?  ...is your instance self hosted?

0 Kudos

The custom menu item is still working; I just tested the refactored code in our Beta instance. 

Follet Discover Global Navigation Button above Help Button

Our instance is not self hosted.

Hello again!

If we were trying to add two custom menu items, let's say one called 'University Support' and the other 'Zoom' to appear before the help icon, what would I need to change in the js code to structure the icons that way? 

Try viewBox="0 0 156 156" for using a custom image. Our sizing was a problem but we kept trying different figures to get it as close as possible to the standard icons. 

kenneth_rogers
Instructure Alumni
Instructure Alumni

Alright,  @kenneth_larsen ​ - I'm running into some issues here, and not sure where I'm hung up. I *think* I have the code for my menu items correctly, but not sure exactly what line to put my three menu items on?

You can add the items right after the function. I did notice that the above entry insists on adding in <span> and </span> into the item code. I tried editing the entry to take them out but they showed up again. You will probably want to wrap the items in a document ready function as well so that it makes sure the page has finished loading. That would look something like:

$(document).ready(function() {

  addMenuItem('Library', 'http://url.com', 'icon-educators');

  addMenuItem('Item 2', 'http://url.com', 'icon-envelope');

});

kenneth_rogers
Instructure Alumni
Instructure Alumni

 @kenneth_larsen ​ You're the best. Took the day off on Friday and took a nice Sunday afternoon to wrap up the code that you provided. Everything works beautifully. I really appreciate you, sir!

Here's my sample of what I wanted to accomplish (this icons are from the Canvas Style Guide):

menu_resize.gif

If anyone wants the .js file of what I used (the links will point back to our site), I've got it in my personal dropbox account. Feel free to use it - it all came from  @kenneth_larsen ​!

Dropbox - new_java_10272016.js

Thank you! I added this to our test site and it looks fantastic. I just have a quick question about my menu items opening in a new window. I've added '_blank', but was unsuccessful at having the new window open. Any suggestions?

var styleAdded = false; 

    function addMenuItem(linkText, linkhref, icon) { 

        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').append(itemHtml);  

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

        if (!styleAdded) { 

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

            styleAdded = true; 

        } 

            

    }

$(document).ready(function() { 

addMenuItem('Daymar Email & Office 365','https://login.microsoftonline.com/', 'icon-email','_blank');

addMenuItem('Portal','https://portal.daymarcollege.edu/secure/Student/loginstu.aspx?ReturnUrl=%2fsecure%2fstudent%2fstuden...', 'icon-star','_blank');

});

jtorres​, I did some digging to try and find the code that  @kenneth_rogers ​ was talking about and apparently found a version that was before adding the option to open in a new tab. I have updated the code above to include that addition. You will only need to replace the function part, you can keep the lines where you are setting up your items.

Let me know if I forgot anything else :smileylaugh:

Brilliant! Thank you. It worked beautifully!

 @kenneth_larsen ​ as always - you're the best. jtorres​ - you prove why this Community is awesome. When someone (me) overlooks something, there's someone else going "Hey, I don't think that's *quite* right...yet." Plus, you saved me looking like the jerk bugging Kenneth for more free code! :smileylaugh:

Updated code worked amazingly well for me, too...but it came from The Kenneth Larsen, so that's to be expected, right  @kenneth_larsen ​?

Hi, Kennith - what's the trick to getting two/multiple custom global options to show?  What code needs to be added/adjusted in the CSS and/or JS files?

Hi,  @JACOBSEN_C ‌! I was just whipping up a response to your question below for you!

To add the three items in our menu, we used the following code in the .js file (no CSS):

252429_menu.jpg
addMenuItem('Student Quick Guide','https://alamo.instructure.com/courses/293886', 'icon-note-light', '_blank');


addMenuItem('Technical Support','https://alamo.instructure.com/courses/293886/pages/technical-information?module_item_id=2163467', 'icon-settings-2', '_blank');


addMenuItem('College Resources','https://alamo.instructure.com/courses/293886/pages/college-resources-and-contacts', 'icon-collection', '_blank');

These were done on lines 50-52 on this file. Essentially, it's telling the function to:

  • Add the Menu Item
  • What to name it
  • Where it's located
  • The icon we are using (from the style guide)
  • And that it's opening in a new window

Kenneth - this is Great!  Much appreciated!  ... got any idea on how to slip the custom options above the help icon?

Man. That's where you've got me. I like to say that I can read and understand some programming languages, but to write something?! Yeah, that's not happening! (Except HTML and CSS - gotta throw that in there!).

Looking over the .js file I included, when it's building the html portion, it appears to say that it is building what the function will do in lines 37-41 (as I mentioned above), and then it takes the itemHTML and appends it to the menu in line 42. Granted, I could be totally off here, but that's what my brain reads.

I'm going to tag  @kenneth_larsen ‌ again, because he's the best. If I'm way off base, he'll tell us! 

Hopefully this is possible for you!

You should be able to change the following line in the JavaScript from:

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

to: 

$('#menu .ic-app-header__menu-list-item').last().before(itemHtml);

This will find the last item in the menu and insert the new item before it.

This seems to work really well, Kenneth!  Thanks for helping us out.  We appreciate it!