Course Roster Enhancements

James
Community Champion
22
14816

Synopsis

Add functionality to your course Roster page by 1) sorting on any column, 2) generating a PDF of the roster, or 3) creating a Photo Roster.

Although this is placed in the Higher Education group, it's only because Canvas requires blogs to be put somewhere and I teach at a community college. K-12  can benefit and Canvas Admins  should be aware in case their faculty want to do these things. It deals with programming, although not specifically API, LTI, or SIS, so maybe the Canvas Developers would want to know about it. Basically, share it with anyone who you think can benefit from it.

Introduction

Several people have asked for features related to the Course Roster page.

  • (94 votes, July 22 update: not happening in the next 6 months)
  • (archived)
  • (8 votes before it was archived as a duplicate)
  • (20 votes, currently open)

I have been having some success installing user scripts to work with Firefox and Greasemonkey, although those were short enough that I could display and explain the code in my blog posts.

I had also added the ability to sort tables to pages before, so I thought ... how hard can this be? Well, it turns out that things are much harder than I anticipated, but that is perhaps a topic for another blog post. For this one, I'll get to the point.

Available Scripts

In the end, I had three scripts, depending on how much functionality you want. All three of them are attached linked to this blog post. The words basic, intermediate, and advanced refer to the functionality provided by the script, not the user level required.

Canvas only loads 50 users on the roster page until you scroll down. I couldn't find a way to tell if all of the users had been loaded or not yet, but I set up a MutationObserver to check to see if new content is added and place a warning if you try to generate a PDF and there is exactly 50 users in the list (that can be suppressed if it gets in your way). Pagination was, by the way, a huge obstacle to overcome, but not as much as the photo roster.

1. Canvas Roster Sorter (Basic functionality)

This script allows you to sort by clicking at the top of any column on the Canvas Roster page. If you click again, it will reverse the order of the sort. If you click a third time, it will restore the table to its original order.

This is based off of an enhanced jQuery Tablesorter plugin, so read there for more information.

2. Canvas Roster Download (Intermediate functionality)

This script includes everything in the Roster Sorter and adds the ability to generate a PDF of the roster. By default, it only includes students. It displays the name, login information (if available), the section (if there is more than one in a course), the last activity date and total activity amounts (if available).

It adds a button to the right-side menu to download a PDF of the roster.

This uses the PDFMake routines to generate the PDF. They are a higher level attempt to create PDFs to avoid the normal hassle of specifying sizes, but that means some functionality may not be there. I did offer the ability to set the default font size and there are some other options you can use.

3. Canvas Photo Roster (Advanced functionality)

This was the nightmare that wouldn't end. It includes the roster sorter and the roster PDF download as well. It also uses the PDFmake routines to create a photo roster of four students wide. Under the photo is the student's name and section (unless there is only one section in the course). Images are resized to fit the avatar dimensions of 128x128.

It adds a button ot the right-side menu to download a Photo roster.

This one was the hardest to write and it's also the hardest to get working. The first two don't need any special privileges, but the avatars, which are displayed on the page, are part of the CSS background-images and not part of the document object model (DOM), which means that I couldn't get access to them without re-downloading them. Some of the sites hosting them were using cross domain restrictions to make sure that I couldn't download them. And if I could download them, they had a flag set that wouldn't allow them to be added to the HTML5 Canvas (not to be confused with the Instructure Canvas) to create an image out of it.

I'm beginning to see why Canvas said it wouldn't be happening in the next six months.

I worked around all that by using the internal greasemonkey routines rather than jQuery's, but that means I had to enable some options that threw the whole thing into a sandbox and the normal stuff stopped working. The first two scripts don't need this functionality and they load much faster. It turns out that the pdfmake routines don't load in the sandbox, so I had to add them through a getscript() function, which means that sometimes they're not fully loaded when it's ready to create the PDF. Occasionally, a photo will timeout before it gets downloaded (it seems that Canvas may do some throttling).  A warning will pop up if some of the images don't correctly download so that you can decide whether or not you want to go ahead and print. If you don't, usually trying the report again will fix it.

The bottom line is - click the button, but don't expect it to work the first time, especially if you have a large class. Give it about 10 seconds and then try again. Maybe a couple of times. It seems to work fairly well for small classes where no pagination is needed.

Instructions

Installing Greasemonkey

The key to getting all this to work is Greasemonkey, which is a Firefox add-on. For Chrome users, there is Tampermonkey. These scripts are tested with Firefox. I had them working in Chrome, but then as I added more features, I broke something, so for right now, it's Firefox only.

Here is a short video on how to install Greasemonkey. Ignore the part at the very end about installing a user a script - I found a better way.

Install the desired script(s)

After you have enabled Greasemonkey, then click on the appropriate attachment below. Greasemonkey recognizes the extension .user.js and automatically intercepts it. You need to click Install a couple of times (once to install it and once to activate it), but then it should work.

The only configuration that is necessary is if your site isn't hosted on instructure.com. I've set up the // @include in the header to work on any site matching *.instructure.com/courses/*/users but you will need changed if you are using a custom domain.

You should only install one script, although it's possible they might work if you install more than one. It's more likely that you'll run into issues.

Notes

  • If it doesn't work the first time, wait about 10 seconds and try again. This is especially true with the photo roster where it has to download a bunch of stuff. But after you download it, it's in your browser's cache so it should go faster the next time.
  • If you notice Firefox starting to act slowly, you might want to restart it.
  • Patience is key. If you can't find the Patience key on your keyboard, try F12 and click on console. Some messages are logged to the console that might help you track down what's going on.
  • I have tried to automatically determine the columns rather than hard-coding the order, but I have admin rights and see everything on the course users page. If you find something doesn't work, let me know. If you're not using US-English, I did code the headings at the top of the files so you can change those to match the text.
  • Everything is loaded from the users page except for the photos, no API calls are made. If it's not visible on the roster page, it's not going to show up in my stuff.
  • Chrome isn't working yet. I had it working with Tampermonkey, then I added a lot of features and things stopped working. The last error I got was that MutationObserver wasn't a function. Rather than take the time to get it working with Chrome, I thought I would make it available to people and hopefully work some of the other kinks out.
  • I am not turning this into a full-featured roster tool. If you write and ask for features like "Can you make it randomize the order of the students on the photo roster?" I'm going to say, "You've got the source code, have at!". Like most of what I write, I won't use it myself, I'm writing it to contribute stuff to the community and hopefully spark some ideas in other people who will then give back to the community.
  • I'm not a JavaScript programmer. I don't know how to put stuff on GitHub, although that would be a much better way to manage that than using Blog Posts in Canvas.
  • The code is yours to do with as you like. If you do enhance it, you might consider changes back to me to make it available -- or set up a GitHub repository and let me know about it. Since I obviously don't consider myself an expert, I would love to collaborate with people, but so far, no one has stepped up to volunteer. If we could setup a repository of user scripts for Canvas, that would be awesome.
  • Use at your own risk. I've done extensive testing (pagination, GIF images, corrupt images, only downloading the default avatar once, etc.) It's currently handling everything I've thrown at it, but that's no guarantee that I didn't miss something. If you find a bug, find a solution, and then let me know.
  • Only use one of the scripts below. You can install all of them if you like, but you should only enable one of them on a particular page. The first two (sorting and downloading) play well, it's the photo roster that acts up and I would avoid it unless you need it.

January 5, 2016 Update

Canvas has split the Login/SIS ID into two separate columns. I've updated the code to accommodate for this. However, the original attachments are no longer valid, so I've linked to the Canvancement site that will hold the latest versions of the software I'm contributing to the Canvas Community.

22 Comments
sbastian
Community Novice

Once again, you made me a happy camper! None of my students have photos yet, so I'm not sure about the functionality of that but I did install the photo roster script and the sorting feature as well as the download a pdf of the roster feature work great!

THANK YOU!!

James
Community Champion
Author

 @sbastian ​,

If you don't need the functionality of the photo roster, the second script is actually a better one to use. It pre-loads all of the required javascript, which makes it faster and less susceptible to network and timing issues. It also avoids the sandbox needed to download images, which means that just generally plays better and life is simpler.

But yeah, at least one time, even without any photos, it's awesome to click that Photo Roster button just so you know what it does in case someone asks Smiley Happy

sbastian
Community Novice

Well I'd LIKE to have the photo roster (I am horrible at remembering names so I want to use it to study) but we haven't begun classes yet and my students are freshmen - I'm going to task them with adding their photos day one (Tuesday)!

Right now though...nothing happens when I click Create Photo Roster....is that expected behavior if there are no photos?

James
Community Champion
Author

The "nothing happens" is what normally happens the first couple of times you try it until things get loaded into the browser's cache. It should not be a long-term regular behavior. That's where the try it again and the press F12 key and look at the console things come in.

If it turns out that your default Avatar URL is not the one I coded into the script, you can change it. There are lots of options in the script, but I only tested it on our instance of Canvas. In _theory_ it should work for others.

There is a slight chance that not having any photos at all causes a misbehavior, but I think it's more likely the try it again until it works thing -- waiting 10 seconds or more between each one, depending on how many students you have.

Sylvia_Ami
Community Contributor

Thank you  @James ​.  This is better than what I expected.  I couldn't tell if this is for the current or new UI.  Do you see any problems using this for the new UI? Do any adjustments need to be made?

James
Community Champion
Author

 @Sylvia_Ami ​,

I don't use the new UI, but my understanding is that the content within the pages themselves hasn't changed, just the layout and formatting of them. I don't read anything based on position on the screen, I read it from the HTML tags associated with it on the page. In that sense, it should work with the new UI as well as the old one. The styling of the buttons may not be on the right side any more (I don't know for sure), but they should be in the same grouping as View User Groups, View Prior Enrollments, View Registered Services, and Student Interactions Report (give or take depending on your permissions).  I copied the existing code for those buttons and matched them to make sure they would act and appear the same.

I said "right side menu" because that's where it is on my screen and the actual HTML in the page has it inside a div with an id="right-side-wrapper". Seems that Canvas wasn't forward thinking enough about the names for things when they designed stuff. At this point, it would involve changing a lot of code to modify it, so they will probably leave it called "right-side-wrapper" and just style it to appear somewhere else if necessary.

kona
Community Coach
Community Coach

This was beyond ridiculously easy to install and use. I already had Greasemonkey installed from the Sorting Rubrics Made Easy​ and How to List Items Alphabetically when Adding to a Module​, so literally all I had to do was click on each file name and it installed itself on Greasemonkey automatically within seconds. Yes, that quick and that easy. Yay! I then went to the People tab for one of my classes and there were the two beautiful new buttons - "Download Roster as PDF" and "Create Photo Roster." They align perfectly with the other Canvas buttons on the right and look like they are just part of Canvas! Both worked for me with no problem! I also tried out the different sorter features and love them! It's really nice to be able to sort my students by the last time they logged in and their total activity - I know these things don't mean everything, but it's a nice quick indication if something is wrong! Thanks for your hard work on this  @James ​!

RosterPrint.png

kona
Community Coach
Community Coach

 @Sylvia_Ami ​, I just tried all three scripts in the new UI and they worked perfectly, no problems at all.

RosterNewUI.png

sbastian
Community Novice

Regarding my earlier comment about nothing happening when I clicked Create Photo Roster - I now believe that WAS due to no students having photos.

I met with my class this afternoon and several have already followed directions to upload a photo to their Canvas profile. And now when I click Create Photo Roster, it works like a charm.

Another home run from  @James ​!

Sylvia_Ami
Community Contributor

Thank you  @kona ​. I appreciate you taking the time to test this. We are going to the new UI in a few weeks so I'm making sure things will transition smoothly.

canvas_admin
Community Champion

Simply amazing!

canvas_admin
Community Champion

For those who are using the Photo Roster, are you still able to get it to work after all of these Canvas updates?  Mine is no longer working.  I can download the PDF Roster and sort the roster, but not the Photo Roster.

James
Community Champion
Author

 @canvas_admin ​, It stopped working with some of the changes that Canvas made earlier in the year. I made some adaptations a month ago to get it working again and then started reworking it to make it better (it was one of my earlier scripts and I've learned a lot about JavaScript since then) and never got it finished. The changes were on my local end and I never uploaded them to GitHub because it never got working quite the way I wanted.

At the time, I saw where someone else had published how to make a photo roster, so it went on the back burner.

So, yes, I can confirm that the photo roster is not working right now.

canvas_admin
Community Champion

 @James ​, thanks for letting me know.  Do you recall where in the community you saw the other reference on how to make a photo roster?

James
Community Champion
Author

Sorry no. A search may help -- or not -- depending on what groups you follow.

RobDitto
Community Champion

An idea to add standard tabs at People for sorting has just been resubmitted. If you're still interested in having that become a feature (I sure am), please vote on:

christopher_gil
Community Coach
Community Coach

hey at @James I finally installed the script for sorting people, but was wondering if you knew why it may stop working as soon as I choose to filter Roles? Basically when I choose "Student" role the function of sorting by activity or other no longer works. 

 

Thanks James! 

 

Chris 

James
Community Champion
Author

Chris ( @christopher_gil )

Based on your description, I had an idea of what was going on. I checked it out and confirmed my suspicions. It stops because the list is reloaded from scratch (rather than filtering the existing content) when you select a role. This removes the tablesorter functionality from the list and since the script is no longer running, it ceases to work.

The way I wrote the script is to run once when the page is first loaded and to stop watching the page once all of the students are loaded. To fix it so that it works after filtering is applied would need to use a mutation observer to watch for when the content is completely reloaded. Right now, there is a mutation observer to wait for the table to appear the first time, but then I remove the observer to make sure I'm not slowing things down.

The fix is more complicated than just removing the line that disconnects the mutation observer. It may involve adding a different observer to see when the list is destroyed / recreated and then re-adding the functionality. It looks like adding a mutation observer to "#content div[data-view="users"]" and watching for the childList mutations would be sufficient. Of course, that div isn't there when the page is loaded, so I still have to keep the existing mutation observer to wait for the initial load.

Fixing that is a lot easier to do than writing the script in the first place, but when I revise a script like this, I normally do more. I've got a tiny bug written on a whiteboard that has been sitting there since pre-covid that needs fixed as well (it fails to detect the time when there are no minutes: example 3am). I also noticed that I had a parseInt() function without specifying the radix (at the time, I missed the warnings that 10 is not the default).

Next week is finals and so this week is filled with grading assignments for students trying to save their grades. I cannot guarantee a timeline of when I can fix it, but I'll try to get it working.

christopher_gil
Community Coach
Community Coach

Hi @James you are the best, thank you for sharing the insights as to what is happening and you are able to resolve it, wow that would be amazing! I stumbled upon because our online school needs a better way to take "attendance"  and with many teachers having over 140 kids in the class it is hard to sort;.

Thanks again James!

 

Chris 

James
Community Champion
Author

Chris ( @christopher_gil ),

I'm close to having something -- I hope. I reworked most of the code and I'm in the testing phase to make sure it still works. It works with my classes -- with English as the language. It reads the date from the tooltip rather than the text because Canvas doesn't show "Dec 1, 2020" in the text, it just shows "Dec 1" and so you might think access was yesterday when it was a year ago if I did that.

One of the things I've missed since Canvas removed the internationalization support is the ability to support different languages without having to hard-code information that was already in Canvas. My old script relied on the names of the columns matching the configuration, which is very much an English thing. Now I'm basing it on position and the presence of attributes on the elements so it doesn't rely on the language. I'm also trying to generate the names of the months programmatically so it will pick up Spanish or other language rather than only working with English.

I also removed the code that specifies all the extra information that was needed to make it support English, so there is a lot less configuration (as in none) needed unless you don't run on *.instructure.com.

I made it easier to specify the format of dates so I will be able to add support for other languages, but I don't have anything other than English entered right now.

It, obviously, works when the filter is applied and the data is reloaded since that was the whole impetus for this.

I also need to test that it works with more than 50 students, but I didn't change that part of the code, so I'm expecting that it will.

I'm not releasing it just yet and I need to go get the kids so I won't be able to work on until later tonight. But, it's mostly an issue of just testing things, fixing things that don't work, and adding support for more dates at this point.

James
Community Champion
Author

@christopher_gil 

I've updated the GitHub site with version 8 of the code.

Here are some of the changes in this version.

  • Filtering the data is now supported.
  • Support for different languages
  • Column detection doesn't rely upon matching text
  • Dates and times support different languages
  • Support for times where minutes are 0 so that 3am sorts properly
  • Major code rewrite and cleanup.
  • Updated jQuery and tablesorter to most recent versions.

At some point, I should write a new blog post as most of this one applies to scripts that are now deprecated.

James
Community Champion
Author

January 10, 2022 update:

In my major update last month, I broke proper detection of times in the 12 am hour. This has been fixed in version 9.