Changing the Canvas UI with Custom JS
By Liam Beveridge
Canvas’s user interface is designed to work well for a variety of schools, but it is not always optimized for the needs of a particular school. There are options to control many Canvas features, but most of the Canvas UI can’t be changed with Canvas’ built in settings. Fortunately, Canvas allows admins to upload custom Javascript and CSS that can automatically run on every page. Through custom Javascript, admins can directly edit the Canvas UI and tailor it to their institution’s preferences. In this article, we will cover an example of custom Javascript we have implemented in Canvas to show that admins can make helpful changes with a relatively basic understanding of HTML and Javascript.
We started receiving feedback that the course list on the profile page of students was difficult to navigate when the student had been enrolled in a large number of courses. The courses on that page are listed alphabetically, regardless of when a student took a course, so over multiple years, the list gets very long. When teachers or counselors go to a student’s profile and need to quickly open all of that student’s current classes, they may have to scroll past dozens of inactive courses to track down each active course. We determined that if the list of courses was sorted so that all the active courses were listed first instead of listing all the courses alphabetically, school staff could much more conveniently access all of a student’s active courses. This turned out to be a fairly straightforward change to implement using Javascript in Canvas. As an introduction to using custom JS in Canvas, here is a breakdown of the function we use to re-order the course list on users’ profile:
function reorder_profile_course_list() {
let currentPage = window.location.pathname;
if (currentPage.includes (“/users/”) && !currentPage.includes (“user_notes”) && !currentPage.includes(“courses”)) {
var list = document.getElementsByClassName (“unstyled_list context_list”) [0];
// Optional line to double the height of the courses list:
//list.style.maxHeight = “400px”
var items = list.getElementsByTagName(‘li’);
var stop = 0;
index = items.length - 1;
while(index > stop) {
if(items[index].classList.contains(“active”)) {
items[index].parentNode.insertBefore(items[index], items[0]);
stop++;
} else {
index—;
}
}
}
}
First, we need to ensure that we are on the correct page to run this function. The URL for the profile page should match the format “https://school.instructure.com/accounts/#/users/###.” We use “window.location.pathname” to get the current URL. Then, we check if the URL contains the word “users.” There are two other pages that include “users” in the URL that we do not want to run this function on, so we check that the URL does not contain “courses” or “user_notes” to ensure that the current page is not the course-level profile page or the faculty journal.
Next, we need to get the HTML element for the courses list so that we can re-order it. By inspecting elements within the page using Chrome’s developer tools, we can find that the course list element has the class “unstyled_list context_list.” If we run “document.getElementsByClassName("unstyled_list context_list"),” the only element that is returned is the list of courses. We can save it as a variable with “var list = document.getElementsByClassName("unstyled_list context_list")[0];.” Then, we can create an array of the courses within the list using “var items = list.getElementsByTagName('li');.” Finally, we can iterate backwards through “items,” moving any active courses to the front of the array. By iterating backwards, we keep the active courses in alphabetical order as we move them. To make the courses list more readable, we can also increase its size with “list.style.maxHeight = "400px".”
window.onload = function () {
$(document).ready(function() {reorder_profile_course_list()})
};
Now, we just need to add the above code to run our function. “window.onload = function () {“ ensures that our code runs whenever a page is loaded in Canvas. We call our function using jQuery with “$(document).ready(function(){validateObserverRole()})” to ensure that the DOM is loaded and can safely be manipulated before our function runs. With our code complete, we can follow Canvas’s instructions for uploading it into our Canvas theme. After the theme has applied, each user profile page in Canvas will automatically sort active courses to the top of the courses list.
This simple customization just scratches the surface of what we can do with custom Javascript in Canvas. More extensive projects we have implemented include sorting the “All Courses” page by individual students for observers with multiple students, and a program that changes the color of students’ names for staff to indicate if they are enrolled in any special programs.
There are a few limitations to keep in mind when working with custom Javascript in Canvas. Anything that is run in an iframe, like the Canvas gradebook, unfortunately cannot be accessed by custom Javascript. Additionally, any custom code could hypothetically be broken by a future Canvas update, so it's important to test things in your beta instance when any relevant Canvas updates are scheduled to be launched. With those caveats in mind, Canvas custom code can still be applied for a variety of purposes. Whether you just need to hide a button, or implement entirely new functionality, we recommend keeping it in mind when Canvas’ out of the box features could be improved for your use case.