cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Learner II

Custom JavaScript/CSS Changes

Jump to solution

Hello all,

Question. Over the weekend there was a Canvas Production Release. In the notes, it mentions undocumented changes to the CSS/Javascript. It seems that those changes have broken our Resources Tab, specifically the slide out menu. We've tried rewriting the code, and even used the code found here as a basis: canvas-contrib/Branding/JS_and_CSS/react-tray-link at master · kajigga/canvas-contrib · GitHub 

Has anyone else had this issue or have any thoughts/ideas as to what has changed?

Thanks!

1 Solution

Accepted Solutions
Highlighted
Instructure
Instructure

Hey Everyone,


I'm an Engineer that works on canvas and I wanted to help clear up what changed and how to fix it going forward here so I made a quick screencast.

Basically the issue was that we used to use a JavaScript library we created called "ReactTray" which was a precursor to the one we officially added to InstructureUI. The latter is better because it fixes a bunch of bugs, has better screenreader and Right-to-Left language support and there was no point in loading 2 tray javascript libraries on the page since all of the other trays we use in canvas are all already using the InstructureUI one.

but the good news is that you really shouldn't have to use custom JavaScript or CSS to make custom help links,  or to change the help menu's name and icon.  those are all things that are officially supported right in the canvas UI. just click the "Customize this menu" link at the bottom of the tray when it pops open and it will take you to an account settings page where you can create as many custom links as you'd like (see screencast).

And even if you want to add some kind of custom JavaScript behavior when you click on one of those links you can use the officially supported way to add them and add something like this to your custom JavaScript file to handle clicking on them (also see screencast):

// this is not supported by Instructure, I'm just providing it as a reference in case it is helpful
// Replace "http://example.com/test" in the selector with whatever url you use in the link you want to add custom behavior to
$(document.body).on('click', '#help_tray a[href="http://example.com/test"]', function(event) {
event.preventDefault()
alert('do something special')
})‍‍‍‍‍‍‍

Hopefully that helps clear things up. If there is anything any of you are needing that is not possible ‍‍‍‍using the officially supported way of adding custom links, we'd be interested to hear what you are doing. The hope in creating that feature was that there wouldn't be an need to use custom JS for that anymore and that people could do the same thing in a way that was easier, less-brittle, and officially supported.

PS:  I just want to add another reminder to people that are using a Custom JavaScript override file that those modifications are not officially supported and that you should make sure to check beta before every release to make sure your stuff is going to work when it goes to production.

View solution in original post

55 Replies
Highlighted
Community Advocate
Community Advocate

I took a stab at the linked code, it seems on line 105 .ReactTrayPortal no longer exists.

$('.ReactTrayPortal div').append(trayHtml);‍‍

$('.ReactTrayPortal').length // result = 0

Changing it to the following, allowed the slider to show me the list of links.

$('#menu').append(trayHtml);‍‍

Not sure if it's a complete solution, but it might get you started.

I have some code that appends content after .ic-NavMenu__link-list, when I came in yesterday it's now ._2j92CzO._17Ovwhm._1eZWDls :smileyconfused:

Highlighted

Thanks, carroll-ccsd‌. We just tried this and now it is still not working. It seems to be a class error...

0 Kudos
Highlighted

How different is your code from the example, would you be willing to post it?

0 Kudos
Highlighted

We originally had this: $('.ReactTrayPortal div').append(trayHtml);

Then we changed it to $('#menu').append(trayHtml); with no change.

0 Kudos
Highlighted

// THIS IS NOT SUPPORTED BY INSTRUCTURE, WORKS as of 12-4-15
$(document).ready(function() {
    if(ENV.current_user_roles.indexOf('teacher') >= 0 || ENV.current_user_roles.indexOf('admin') >= 0){
        //items to show to teachers and admins
        var trayLinks = [
            {key: 'https://msmelo2.squarespace.com/', val: 'MS MELO'},
            {key: 'https://msvcc2.squarespace.com/facultyresources/', val: 'Faculty Resources'},
{key: 'https://sbcjcweb.sbcjc.cc.ms.us/ET/EThome.aspx', val: 'Enrollment Tool'},
{key: 'http://www.holmescc.edu', val: 'HolmesCC'}
        ];
    } else if (ENV.current_user_roles.indexOf('student') >= 0) {
        //items to show to students
        var trayLinks = [
            {key: 'https://msmelo2.squarespace.com/', val: 'MS MELO'},
            {key: 'https://msvcc2.squarespace.com/student/', val: 'Student Resources'},
{key: 'https://sbcjcweb.sbcjc.cc.ms.us/ET/EThome.aspx', val: 'Enrollment Tool'},
{key: 'http://www.holmescc.edu', val: 'HolmesCC'}
        ];
    } else {
        //items to show to people who are not teachers, students or admins
        var trayLinks = [
            {key: 'https://msmelo2.squarespace.com/', val: 'MS MELO'},
            {key: 'https://msvcc2.squarespace.com/student/', val: 'Student Resources'},
{key: 'https://sbcjcweb.sbcjc.cc.ms.us/ET/EThome.aspx', val: 'Enrollment Tool'},
{key: 'http://www.holmescc.edu', val: 'HolmesCC'}
        ];
    }

    var slide_out_title = "Resources" //Changes the title on the slide out menu
    var global_nav_name = "Resources" //Change the title on the global navigation menu

    var footerContent = ''; //Changes the text of the bottom on the slide out tray
    ////////////////////////////////////////////////////////////////////////////////
    //DO NOT EDIT ANYTHING BELOW THIS LINE!
    ////////////////////////////////////////////////////////////////////////////////

    //Browser Detection
    navigator.agentDetect = (function(){
     var ua= navigator.userAgent, tem,
     M= ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
     if(/trident/i.test(M[1])){
     tem= /\brv[ :]+(\d+)/g.exec(ua) || [];
     return 'IE '+(tem[1] || '');
     }
     if(M[1]=== 'Chrome'){
     tem= ua.match(/\b(OPR|Edge)\/(\d+)/);
     if(tem!= null) return tem.slice(1).join(' ').replace('OPR', 'Opera');
     }
     M= M[2]? [M[1], M[2]]: [navigator.appName, navigator.appVersion, '-?'];
     if((tem= ua.match(/version\/(\d+)/i))!= null) M.splice(1, 1, tem[1]);
     return M;
    })();

    //Array, 0 = browser, 1 = version
    var agent = navigator.agentDetect;
    var reactId;

    switch(agent[0]) {
     case "Firefox":
     reactId = "2";
     break;
     case "Safari":
     reactId = "2";
     break;
     default:
     reactId = "1";
     break;
    }

    var displayVals = '';

    function displayLinks(element, index, array) {
        displayVals += '<li>';
        displayVals += '<a href="' + element.key + '">' + element.val + '</a>';
        displayVals += '</li>';
    }

    trayLinks.forEach(displayLinks);

    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>';

    trayHtml = trayHtml.replace(/(?:\r\n|\r|\n| )/g, '');

    var menu = $('#menu');
    if (!menu.length) return;
    var custom_nav = $('<li/>', {
        'id': 'custom_nav',
        'class': 'menu-item ic-app-header__menu-list-item',
        html: '<a id="global_nav_resources_link" href="javascript:void(0)" class="ic-app-header__menu-list-link">' +
        '<div class="menu-item-icon-container" aria-hidden="true">' +
        '<i class="icon-resources"></i>' +
        '<div class="menu-item__text">' + global_nav_name + '</div>' +
        '</div></a></li>'
    });

    menu.append(custom_nav);

    $('body').append('<div id="customTrayOverlay" style="width:' + $('#menu').width() + 'px;height: ' + $('#menu').height() + 'px;position: absolute;left: 0;top: 87px;z-index: 999;display:none;"></div>');

    $('#global_nav_resources_link').click(function () {
        $('.ReactTrayPortal div').addClass('ReactTray__Overlay ReactTray__Overlay--after-open');
        $('.ReactTrayPortal div').css({
            'position' : 'fixed',
            'top' : '0px',
            'left': '0px',
            'right' : '0px',
            'bottom': '0px'
        });

        $('.ReactTrayPortal div').append(trayHtml);
        $('#menu, .menu-item.ic-app-header__menu-list-item a').addClass('ui-state-disabled').attr('disabled', 'disabled');
        $('#customTrayOverlay').show();
        $('#custom_nav').css('background-color', '#fff');

    });
});
Highlighted

Alan,

I don't seem to have enough knowledge of React to make this work at the moment. When a menu item with a tray is clicked a <span> with no ID or CLASS attribute is appended to <div id="main" class="ic-Layout-columns">, when I try to append similar content, nothing shows up. I feel like Canvas left us without an HTML element to drop the content into, which used to be .ReactTrayPortal div. Multiple events in the contrib code point to this DIV, which doesn't exist.

I want to finish up a project I'm working on, and then I may try to play with this later in the week. Maybe someone else will have better luck.

Highlighted

Thanks! We're going to keep looking as well. A short-term solution is just to add our needed links into the Help Menu, but I definitely feel changes like this need to be put in the release notes documentation.

Highlighted

Agreed...

Also, I typically check all our customization and hacks against beta before they release to production. In this case I think it would have been helpful, because you could compare old to new, and try and swap out the classes/html structure, the primary difficulty being I couldn't exactly tell what changed.

Highlighted
Learner II

So. After a lot of blood, sweat, and tears, we've figured it out. The "undocumented changes" that occurred in the latest production release seems to have changed the inheritance of the code. Things that were not connected previously became connected. Because of this, we've had to change the following issues today:

  • Student grades became hidden because we hide the To-Do List
  • Videos recorded inside of Canvas became invisible because we hide the To-Do List
  • The slide out tray for a customized button was removed, as well as all the inherent links within it.

We've drastically changed the CSS/Js code, so here's hoping no more of these pushes will break our Canvas experience.