Show student names for Differentiated Assignments

James
Community Champion
26
8246

When assignments, quizzes, or discussions have multiple due dates, Canvas gives a summary table of the dates and the number of students, but not the names of the students. This user script replaces the number of students with the names of the students.

Quick Install

For those power users who are impatient, here are the quick install steps.

  1. Install a browser add-on: Greasemonkey for Firefox or Tampermonkey for Chrome/Safari
  2. Install the Show Override Names user script.

The script has been tested with Firefox, Chrome, and Safari using the English language. If you run into problems, be sure to go back and read the instructions before asking for help.

Introduction

Canvas has Differentiated Assignments that allow you to assign different due or availability dates to assignments, graded discussions, and quizzes. People also refer to differentiated assignments as "multiple due dates" or "assignment overrides". I will mostly refer to them as overrides since that's what they are called in the Canvas REST API.

These differentiated assignments show up in the list of assignments as having "Multiple Dates" and you can mouse over them to see a very brief summary of the group and due date.

Differentiated Assignments

Clicking on the assignment name will take you to that assignment page where you will be given a summary table that provides additional details.

Assignment Due Dates

This is a summary table that provides all three dates (due, available from, and available until) as well as the number of students receiving each override. While the table shows the number of students, as shown in the red box, it does not tell you who those students are. If you want to see the names of the students, then you need to edit the assignment, scroll down to the "Assign to" section and then look for the appropriate information.

Assign To

Although the names are blurred in the image for privacy reasons, the student names are provided in "First Last" form, but not in alphabetical order by either first or last name.

Displaying the student's names instead of the counts was the essence of a feature request   by  @ezaurova .

After you install this user script, the summary table on the assignment page looks like this.

Differentiated Student Info

The astute observer will notice that the order is different than it was before. That's because Canvas sorts on the due date and not on the available from or available until dates and the two assignments are both due at 5:05 pm.

The line wrapping isn't as bad with a wider monitor, but the browser decides how wide to make each column based on the amount of information in them. I put in seven names to force wrapping, but it looks pretty decent when there are only a few names. Here is a before/after example from a graded discussion that has three overrides.

Differentiated Discussion 1

Differentiated Discussion 2

Installing the User Script

A user script is a JavaScript that is ran by the browser on the user's machine. Rather than a Canvas-supplied script, it's one that the user installs and runs on their own. The installation is per user and per machine, so you will need to install it on each machine that you want to use the script with.


Install Browser Add-On

The first step is to install and enable the browser extension that allows you to run user scripts.

  • Firefox users should install an add-on called Greasemonkey.
  • Chrome and Safari users should install an add-on called Tampermonkey.

Here is a video showing how to install the Greasemonkey script with Firefox. Note that you do have to restart Firefox for the add-on to be recognized.


Install the Show Override Names User Script

Once you have installed and enabled the browser add-on, it's time to install the user script. Luckily, the browser add-on looks for filenames that end in .user.js and offer to install them for you. That makes installation extremely easy, just click the link below.

     Install the Show Override Names user script

Custom URLs

You shouldn't have to do anything if you're running if your Canvas instance ends in instructure.com. If you have a custom URL, like canvas.university.edu, then you will need to modify the script to get it to work.

The specific steps to do this vary depending on your browser add-on. In Greasemonkey, click on the Greasemonkey pull-down, choose Manage User Scripts, find the Access Report Data, right click and choose Edit. In Tampermonkey, click on the Tampermonkey Icon, choose Dashboard, and then click on Access Report Data.

In either case, you need to change // @include statement on line 5 to match your instance. In the case of canvas.university.edu, you should change it to:

// @include     /^https://canvas\..*\.university\.edu/courses/[0-9]+/(assignments|quizzes|discussion_topics)/[0-9]+(\?...

This is a regular expression that will match the main page for an assignment, quiz, or discussion topic. The (\?|$) at the end is in case you arrive there from either through modules or from the list of assignments, quizzes, or discussions.

Technical Stuff

This section is definitely not required reading. But for those who want to know what's going on behind the scenes, read on.

I had recently written a couple of other user scripts that added functionality to Canvas and thought I could take one of those and make it add the names. I ended up using portions of both and coming up with some new stuff as well. I originally estimated a couple of hours, but had the units wrong and it took a couple of days instead.

The major stumbling block is that Canvas does not provide any identifying information in the summary table other than the information displayed. That means that there is no quick identifier like "This is assignment override # 123654" to uniquely identify the row. I had to scan the information in the table and try to match it with the information from the override tables. Compounding the issue is that Canvas displays the dates and times in some funky human readable form that tries to shorten up the information. Funky human readable form probably means that it's internationalized to use whatever language you're using, rather than English. I could have written it to just work in English, but I thought I would try to write something that others could use. Anyway, the year is left off when it's the current year (Feb 29 instead of Feb 29, 2016) and the minutes are left off when the time is on the hour (12pm instead of 12:00 pm). Then there is another flag thrown in there for those 11:59:59 pm times so that it doesn't display it, but just displays the date instead.

The information returned from the API calls is given in ISO 8601 format like 2016-02-28T22:46:12Z. The task was to take the timestamp and match it up with the displayed date. This is my first attempt to use the I18n internationalization (in anything) so I may not have gotten it right. Instead of relying on parsing "Feb 29" into a timestamp, I focused on converting the timestamp into that funky human readable form. The script looks at the override information and the information in the table and does a comparison.

  1. Look at the number of students. If this is unique for the table, then we have found our row.
  2. Look for an exact match of the dates and/or times by comparing four different forms of date (with and without year) and time (with and without minutes). If all three date/times agree, then we have a match.
  3. If the information doesn't match exactly, then look for information in the same spots. Does the combination of due date, available from date, and available until date in the table match that from the assignment override and there is only one such combination? If so, we've found the match.
  4. Is there only one item left -- if so, it's the remaining entry.

At each step in the process, the entries for any matches that are found are eliminated from the list of available overrides before checking the next step. That makes it easier to identify the ones that remain. It is possible that step 1 might skip something because there were two matches, but after completing step 3 there was only one left. If I reach step 4 and there are still some items left over, I run through the entire process again a few times to make sure it catches as much as it can.

If, after all of that, it still can't find a match, then it just displays the number of students like it did before.

Once it finds a match, it sorts the names alphabetically by the sortable name. That means that the names are sorted by the last name, but displayed in "Firstname Lastname" format. If, for some reason, the sortable name isn't available, it falls back to the regular name.

Discussions and Quizzes contain the assignment override information with the assignment, not with the discussion or quiz. That means I needed to fetch the assignment ID before I could fetch the assignment that contains the overrides. That information is technically available in the Speedgrader URL and I could have saved an API call, but I opted to go ahead and make the call anyway. Once I get to the assignment, I'm actually fetching the list of assignment overrides, which is a beta endpoint in the API, rather than the assignment that contains the overrides because it's smaller and thus faster.

Each override that involves individual students a list of Canvas user IDs for the students, but no name information. I then had to look up the names of the students using separate API calls. There are multiple ways to do that, but I ended up getting a list of course users and specify the user_ids[] of those who have overrides. This was a trade-off between downloading the entire list (very, very slow when there are lots of students) or downloading each student individually (slower because it has more network traffic) I chunk it into blocks of up to 50 students just to be cautious.

Remember that differentiated assignments that refer to sections or to "everyone else" don't get changed, so we only need to look up the cases where you have specified a student by name. If you are specifying more than a couple hundred students by name, you may not want to install this script.

Updating the Script

Every now and then I will make revisions and improvements to the script. Luckily, both Greasemonkey and Tampermonkey make it pretty easy to get the latest version. By default, both will automatically check for updates for you (Greasemonkey once a week and Tampermonkey daily). However, if you would like to force an update sooner, you can do the following:

  • In Greasemonkey, you pull down the options bar from the icon and choose Manage user scripts. Then right click on the Access Report Data script and choose Find Updates.
  • In Tampermonkey, you click on the Tampermonkey icon and choose Check for userscript updates.

Canvancements

This script is a Canvancement -- a Canvas Enhancement. The links in the document point to an installable version of the code, but there is a Show Override Names project page. Other projects can be found on the Canvancement website as well.

26 Comments
degroot
Community Explorer

Hey James,

Is this functionality still working? I installed the script and it gets enabled when I'm on a page with multiple due date students but the names aren't appearing. Let me know if I'm doing something wrong or if I'll need to look at tweaking the script!

Thanks,

Jon

James
Community Champion

 @degroot  

I had to check because I don't use this script regularly, but it appears to be working for me.

If you're sure the the script is being run, then the most likely culprit would be that you're using Greasemonkey.

Firefox changed behavior in late 2017 and Greasemonkey stopped working for any script that needed access to jQuery to load additional information. This script is one of those. A permanent fix would be making sure that you load jQuery with your user script rather than using the one supplied by Canvas. Tampermonkey continues to work (they chose a different way to work around the Firefox changes). 

I'm now recommending that people use Tampermonkey since it works with all of the major modern browsers and it continues to work with scripts that need to fetch information. I haven't gone through and updated all of the blog posts or documents that I wrote to reflect this, but I did make a general announcement on the page that leads here: Canvancements - Canvas Enhancements   Of course, that doesn't help if you found it through a search.

A second possibility is that you only think the script is running. Having it enabled isn't the same thing as it running. In Tampermonkey, a red badge with a number will show up on pages where the script is being run. In Greasemonkey, there's a section at the top that says "User scripts for this tab." However, as mentioned before, it is known not to work with Greasemonkey at the current time.

My scripts run by default on *.instructure.com, but it looks like Northcentral Technical College uses as custom URL for their Canvas of canvas.ntc.edu. I'm not positive on that, it's just what a Google search showed. If that's the case, then the script won't run. You'll need to modify line 5 of the script to point to your Canvas instance. In the example below, line 1 is what it says in the script that ships and line 3 is what you need to change it to. The line numbers apply to the example, it's line 5 in the code.

// @include     /^https://.*\.instructure\.com/courses/[0-9]+/(assignments|quizzes|discussion_topics)/[0-9]+(\?|$)/

// @include     /^https://canvas\.ntc\.com/courses/[0-9]+/(assignments|quizzes|discussion_topics)/[0-9]+(\?|$)/

If the custom URL or using Greasemonkey doesn't explain it, then I'll need more information to work with. I'd start on a Canvas page, opening the developer tools (F12) on the browser and switching to the console tab. Then navigate to the assignment page (or reload it). Look at the error messages and see if anything jumps out at you that looks like it might be coming from a user script.  For example, the error when you try to run that page under Greasemonkey looks like this:

290966_pastedImage_3.png

degroot
Community Explorer

Hey James,

I appreciate the very thorough response. Sorry for not providing more detailed information on my initial post. I am using Tampermonkey in Chrome and it appears to be enabled when I navigate to an assignment page with multiple due dates.

291015_Screenshot_1.png

Canvas.ntc.edu is simply a redirect so when we are actually on the page the URL looks like this https://northcentral.instructure.com/courses/16176/assignments/125051?module_item_id=364044 

I pressed F12 and switched to the console tab and this is what I got.

Uncaught ReferenceError: I18n is not defined
at isMatch (userscript.html?id=e78b0cd9-673c-4493-949c-c95c32a1b920:294)
at findMatch (userscript.html?id=e78b0cd9-673c-4493-949c-c95c32a1b920:237)
at process (userscript.html?id=e78b0cd9-673c-4493-949c-c95c32a1b920:183)
at Object.eval [as success] (userscript.html?id=e78b0cd9-673c-4493-949c-c95c32a1b920:152)
at p (jquery.js:1075)
at Object.fireWith [as resolveWith] (jquery.js:1193)
at y (jquery.js:7538)
at XMLHttpRequest.i (jquery.js:8324)

I went into Beta and removed all of our custom JS and tried again with no success. It must be something with our instance though as I had another user try it with the same results. This is not an urgent matter by any means and I really appreciate the time you've put into these scripts. I'll continue to tinker with it and see if I can get it working.

- Jon 

kevin_schaub
Community Member

Love this Canvancement James.  Something weird is happening for me though.  The names of the students are only showing up if there is more than one student, otherwise it still shows "1 student"  Any idea what might be happening?  Has anyone else reported this?  Thanks in advance!

James
Community Champion

 @kevin_schaub , 

Every now and then Canvas changes something on the back-end and things break. Since I don't use this script (or do much with differentiated assignments), I rely on other people to let me know what it breaks.

I'll try to get a look at it and see if I can find something out. Was this happening in a particular place (quizzes, assignments, or discussions) or all three?

kevin_schaub
Community Member

This happened for me in Quizzes.  I don't have Assignments or Discussions assigned to multiple students, otherwise I'd check those out for you.  Thanks James!

James
Community Champion

Where are you exactly trying to view this? I went into Quizzes, picked one, changed a date for one student, and am getting the name. This is on the quiz page itself. 

311864_pastedImage_1.png

Now, on the syllabus page, it doesn't show that.

311865_pastedImage_2.png

But it never showed the names on the syllabus page.

Nor did it ever work on the main lists for assignments, discussions, or quizzes. This is the expected behavior.

311866_pastedImage_3.png

If you look at the top of the script, there is an include line. It only works on specific assignments, discussions, or quizzes, as identified by by the path. It must be an assignment, discussion, or quiz, followed by a number.

kevin_schaub
Community Member

I'm seeing it after I click on the quiz.  It works for multiple students but not individual students.  Here's a screen shot of what it looks like:

quiz

kevin_schaub
Community Member

Weird thing is that it's working for 1 student in a different quiz where I don't have multiple students assigned to a date:

quiz

James
Community Champion

If I'm understanding correctly, I need to assign different due dates to more than one student. I have done this and can verify that it's only showing the ones with multiple students.

It's much easier to track down the problem once I can duplicate it, so thanks for clarifying and for the screen shots so I could see what is happening.

James
Community Champion

Okay, I know what the problem is, now I just have to fix it.

At some point (at least by April 2017 because I asked a Canvas engineer about it), they stopped exposing some of their variables to the user. The I18n translation was part of that. That's a shame, because it allowed me to see what things looked like in the language the user had selected and it made it easier to support different locales.

Because the I18n variable isn't exposed anymore, the script is throwing an error and stopping execution. That means that's it's getting one converted and not all of them. Once I figure out how to get around the time/date issue, I should be able to get it to process all of them.

Of course, that's a 321 line script, so I may take the time to tweak it. I know a little more about JavaScript now than I did then and some of my early scripts were very hackish. Now they're just moderately hackish.

kevin_schaub
Community Member

Thanks James.  I'm glad you were able to replicate it.  With so many things in Canvas, I often think it's just me experiencing it 🙂

James
Community Champion

I started refactoring the code last night, trying to remove the jQuery dependency. I've already removed two API calls that it turns out aren't necessary because the information is contained in the ENV variable (web browser only, but this never worked on mobile apps anyway). If I could find a deterministic way that the overrides are displayed, then I could possibly bypass the date / time check and remove the need to try and convert the human friendly times that Canvas gives but relied on the I18n internationalization to support other locales besides US English. The good news is that the code is getting shorter, not longer. But I had to finally quit and go to bed about 4:30 this morning.

kevin_schaub
Community Member

Ouch!  That's dedication.  I'm happy to test out all your hard work whenever you're ready.  Hope you got some sleep!

kevin_schaub
Community Member

Hi James.  Any chance you have a new release ready for testing?  Thanks!

James
Community Champion

No, I worked heavily on it for a couple of weeks and then got distracted and haven't been able to get back to it. When I pull it up to work on it, it's hard to get back into the swing.

I was able to rewrite it to use better fetching of the data and now have it to the part that was the original problem -- determining the matches without looking at the date. Canvas sorts them in order by due date ... provided there is a due date. Beyond that, I haven't been able to find any deterministic sort order.

Ron_Bowman
Community Champion

@James  -

does this script work if a course is cross-listed?  The only reason I ask is that it is working in one of my courses that is not cross-listed, but it is not working in the cross-listed course.  it may be that the courses that I cross listed each consist of two courses that were merged by the admins into one course and then I cross-listed those merged courses.  I am wondering if that is messing with what you have to look for in the page.

Thanks for your time.

Ron

James
Community Champion

@Ron_Bowman 

Ron, our institution doesn't use Canvas' cross-listing so I don't have anything to test it with. We combine students from multiple sections into the same Canvas course, but that's done by just specifying the section on the SIS import rather than using the cross-listing feature.

Right now, I don't know if the script works at all (other than you say it does). It looks like I started to do some work on it in 2019, but never finished it and moved on. If I remember, it was the logic trying to decipher which override was which that bogged me down.

It is fetching the users using the /courses/ endpoint rather than /sections/ and that might be different in a cross-listed course since they may not actually be in the course (but in a different one).

Can you check out an API call on your end and see if it's returning all of the user information? If you know how to make an API call, great, if not, I'll give a way to do it in a browser.

What I need is <instance>/api/v1/courses/123/users?per_page=100 where the 123 is the courseID for the course that you're trying to run this in. You can just do that in a browser if you don't know how to use a REST client like Postman or Advanced Rest Client. What I'm after is whether you get the full list of students or just the ones in the main course and not the cross-listed one. If you have more than 100 students, you may need to skim through the list looking at names instead of trying to count them. A quick way to count is to use the browser's Find (Ctrl+F) command and then search for "id" (include the quotes). There's only one of those per user, so if it says 1/29, then you know there's 29 students.

Ron_Bowman
Community Champion

@James 

I do not know how to do api calls. How do I do the <instance>... in a browser?

I tried just putting it in where url's go, and I got a search on that which gave a response to a canvas questions as one of the search results - that showed a jquery command which I really don't know how to do either.

Ron

Ron_Bowman
Community Champion

@James -

I figured it out.  <instance> is my schools *.instructure.com address.

I get 85 students listed which is the number in the course with all the sections merged and cross-listed..

Ron

Ron_Bowman
Community Champion

@James 

I did a comparison of the data fields between the course that is a regular course and my cross listed course.  All the information fields  from the api call are the same (no extra fields introduced in the cross listed course).

James
Community Champion

That strongly suggests that it's not the cross-listing that is the issue and that we should look somewhere else.

Did you have multiple overrides for the assignment that's not working? Part of what I was working on in 2019 before getting sidetracked was determining which students matched up. For example, if Canvas just said "4 students" but there were a couple of them that said "4 students" then there may not be a good way to tell them apart, especially if the date and times were the same (parsing the date and time was one of the issues I was having with the i18n object disappearing). I cannot remember whether I checked both the number of students and the dates or just one of those (including which one of those).

Ron_Bowman
Community Champion

@James 

I do have multiple over-rides on the assignment.  usually just one student, but I have had groups as well.  I tested it out with an assignment -

1) 1 override student only - script works

2) 2 or more students in the same override group - it works

3) 1 student in each of a multiple number of overrides - does not work(different dates)

4) 1 or more student in each of a different over-ride group does not work (obviously because #3 did not work)

So I believe your memory is serving you well.   I could have sworn that I have seen it work with multiple groups of students before, but I guess I am wrong.
I really appreciate you looking at this.  If I knew what was going on with accessing the Canvas data and javascript, I would play around with it myself and see what I could figure out.  

Looking at your scripts, I see you comment code about as well as I do when I write it in C++ or bash scripts (although I have become better about commenting as I got older and I found my memory of what I once thought was trivial requires a lot more thinking to figure it out again)

Ron_Bowman
Community Champion

@James 

I went back and looked at something from last semester.  I was correct, it has shown up with multiple dates and multiple number of people for those dates - on  a quiz and assignments (regular course - not cross-listed). 

I played around a lot with my current course.  I saw some strange and inconsistent information.  With  more than 7 overrides, I stopped seeing the names.  With 7 overrides I saw the name for a single student override only - and I could reload the page and have their name toggle back and forth between student and their name.  6 or fewer it seems to work okay.  (Now know the cause of what is going on here - see below)

===>  BELOW HERE is the key I think to solving the issue

==> I tried an assignment with various combinations of over rirdes (adding sections, individual students and groups of students) - I had no issues with seeing student names in groups of 1 or more and with more than 7 different overrides.  The key here was I did not provide dates for any of the overrides.  So, I went back and started adding due dates only.  What I found is that for overrides of groups of a unique size, the names appear.  For multiple overrides for groups of the same size, the names disappear and I just get student.  So with dates and multiple over rides of the same group size, the functionality stops working correctly.  Dates with unique group sizes is not an issue.

 

 

James
Community Champion

@Ron_Bowman 

I think what you're describing is the same issue I ran into when I tried to work on it in 2019. At that point, I noticed that Canvas does some kind of sorting of the entries based on date. I think I was trying a multiple pass effort to go through and find the corresponding entry (first pass -- look for unique counts, second pass -- look for unique dates among what remains, etc.). I don't even know if I have the code I was working on in 2019 anymore, I did a reset of Chrome to speed things up and I think it wiped my working copies of things.

The table that is displayed in Canvas doesn't have any IDs that make it easy to tell which entry is which. The order delivered by the API call is not the same order it's displayed in (that would be too easy). Parsing the dates is language specific and if I don't want to include a library, then I'm limited to US English and the script won't work for others (it probably doesn't right now anyway).

Unfortunately, my memory is much better than my ability to complete projects, so there's a lot of stuff I remember working on and with a little jolt, even what I was trying to do, but never finished. Since COVID, almost all of my time has been spent working on my classes. Free time to do fun programming almost doesn't exist and any coding I do is almost always related to my classes to automate tasks (transfering H5P interactive grades into Canvas, automating Canvas Studio tasks, and et. al.).

Ron_Bowman
Community Champion

@James -

Thanks for the information.  I understand completely about the teaching during covid mess.  My wife and I both teach at a university and someone told us of course professors want classes to go online.  That way all they have to do is answer a few emails.  Don't I wish.

Now that I understand whats going on, don't worry about it.  At least I now know what is happening and I won't be worried about it if the names don't show.