Sorting Rubrics Made Easy

James
Community Champion
50
35214

Quick Install

  1. Make sure a user script manager such as Tampermonkey is installed and enabled.
  2. Install the sort-rubric.users.js file

More information is available on my Sort a Rubric Canvancement page.

Update: October 24, 2019

With the October 23, 2019, deployment, Canvas changed the way that jQuery is loaded so that it will be available for your custom global JavaScript and you won't have to worry about it. However, all of the scripts now have async loading, which is a good thing, but it means that the script manager was injecting this script before jQuery was loaded and it failing.


I took the time to update the script and improve the coding. It was one of the early ones I wrote before I knew much about what I was doing.

 

Note that the blog post below refers to Greasemonkey. Tampermonkey is now the recommended userscript manager. Also do not use the source code in the original blog post -- it will no longer work.

Update: May 3, 2016

Why the Update?

The original blog post (below) talks about copying and pasting into GreaseMonkey. This was one of my earliest attempts with user scripts and I've since learned how to make them really, really easy to install, but the documentation was in the comments to this blog post and people were missing it and still trying to follow the original instructions.

I didn't want to lose the blog post, because it explains what happens and has videos that show it in action, but most people want a plug-n-play, drag-n-drop, or click-n-go solution, and that's what you get through the quick install. Please use the Quick Install and read the instructions and comments below if you care to know what it's doing or run into trouble.

Original Blog Post: August 25, 2015

Synopsis

The ability to sort (drag and drop) rows of a rubric can be made transparent so that it automatically runs on the Rubric editing page. The techniques shown here open up a whole world of solutions to "I wish Canvas would ..."

Introduction

On August 16, I wrote a blog post illustrating how you could inject two lines of JavaScript into a page sort the criteria in a rubric: How to Reorder Rubric Criteria

Since then, I've learned more and found a new technique that blows the first way out of the water. It allows for automatic injection of the JavaScript based on the URL, so it only loads on the Rubric page on your site. But then it automatically runs, you don't need to do anything other than enable it. It works with the Javascript already included on every Canvas page. it downloads the libraries you include when you save the script so that loading them is almost instantaneous.

This is so much easier than the first blog that I'm almost tempted to pull the first one down, except some people have linked to it and it illustrates some of the technical details that this one omits. So if you want to understand more about what it's doing, go read that.

Let's begin with a 55 second video demonstration of what to expect. Notice that when I get to the Rubric editing page from Outcomes > Manage Rubrics that the rubric was automatically sortable once it loaded. That's the beauty of this over last week's method, you don't need to do anything special once it's set up, it just automatically allows you to drag and drop rubric rows.

Instructions

The key to doing this is Greasemonkey, which is a FireFox add-on. For Chrome users, there is Tampermonkey. I haven't tested Tampermonkey myself, but the principles are the same.

Here is a video that shows everything needed to accomplish the rubric editing demonstration above. It begins with the installation of the Greasemonkey, shows how to include javascript libraries, and explains what the code does.

Greasemonkey User Script

This is all about User Scripts. User scripts are scripts that the user creates that runs on the page. Last week, I was talking about bookmarklets that someone could click on to run on the page after they clicked the Edit Rubric button. This is automatic - you don't need to do anything other than enable the script. It's also a lot easier to create than a bookmarklet.

// ==UserScript==
// @name Canvas Rubric Sort
// @namespace https://people.richland.edu/james
// @description Injects the RowSorter.js jQuery library into Rubric Pages on Canvas
// @include https://richland.instructure.com/courses/*/rubrics/*
// @include https://richland.test.instructure.com/courses/*/
rubrics/*
// @include https://richland.beta.instructure.com/courses/*/
rubrics/*
// @require https://gist.github.com/raw/2625891/waitForKeyElements.js
// @require https://cdn.rawgit.com/borayazilim/rowsorter/master/jquery.rowsorter.min.js
// @version 1
// @grant none
// ==/UserScript==
waitForKeyElements('.rubric_container.rubric.editing', attachRowSorter);
function attachRowSorter() {
$('.rubric_table').rowSorter();
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

That is the complete code. Let's take a look at what each line does.

  1. Define this as a Greasemonkey user script
  2. The name of the script
  3. A URL or URI to identify the author in case two or more authors have the same program name
  4. A brief description of what the script does
  5. Run this script on pages matching the main Canvas instance for your site. The main page for editing rubrics is /courses/*/rubrics/*, where * is a wildcard
  6. Run it on the test site as well - optional
  7. Run it on the beta site too - optional
  8. Inject the waitForKeyElements javascript library. This will make sure that the rubric is done loading before you can sort it.
  9. Inject the RowSorter javascript library. rawgit.com allows you to link to any GitHub hosted file, so you don't have to install your own version like I wrote last week.
  10. The version of the code - this is up to you to maintain (or ignore)
  11. The grant statement gives special permissions, none are needed
  12. End the header
  13. The rubric_container and rubric classes are already present. The "editing" one gets added when you click Edit Rubric, so wait for that class to be added to the table, then call the attachRowSorter function.
  14. This function is called after the "editing" class is added by the user clicking on the Edit Rubric button.
  15. Add the rowSorter() method to the rubric_table.
  16. End the function

Every time you make changes and save the code, it will automatically get the javascript libraries on the @require lines so that it's hosted locally and doesn't have to be downloaded when you run the script.

The only changes that you need to make to this script are lines 6-8, where you define where your Canvas instance is loaded.

Using Greasemonkey

Greasemonkey is relatively easy to use. As long as it is enabled, it will check the pages for a match against the @include lines in the header. If you want to disable Greasemonkey, go the monkey and click on Enabled to disable it.

There are a couple of ways to edit a script. If you are on the page where the script would be executed, the name of the script will appear the bottom of the menu. Just right click your mouse on the name and it will load it for editing. The second way is to go to Greasemonkey > Manage User Scripts and then right click your mouse on the script you want to edit.

Notes

  • When you drag and drop rows, make sure you grab the description (left) or the points (right). Do not try to drag one of the items in the middle, the formatting goes crazy and you can't do anything. If you do that, reload the page and edit again and don't drag in the middle.
  • If you want to disable the drag & drop editing, then go to the Greasemonkey on the menu and disable it.
  • Greasemonkey scripts run after the page is loaded, so you have access to jQuery.
  • Greasemonkey is synced with Firefox so it will follow you from machine to machine if you have sync setup.

No Global Javascript Access? No Problem!

In case you haven't realized the ramifications of this, it allows you to add your own JavaScript to Canvas like you had access to the global JavaScript page.

That means that regular users can add their own features, even if the administrator's won't put make the changes globally.

You should, of course, not use it for features that you want your students to see because they won't be able to see it -- it's local to your machine. However, it is useful for development and for teachers. For instance, want to add the ability to sort tables by clicking at the top of a column -- you can do that.

Want to automatically create a rubric based on an Excel spreadsheet -- well, that's going to take some work. But let your imagination run wild.

50 Comments
sbastian
Community Novice

Ooh! Thank you for this! I used to use Greasemonkey years ago, but had forgotten about it!

I'm off to give this a whirl!

sbastian
Community Novice

OK that was EASY! And it works like a charm! You rock,  @James ​! You just made my life a lot easier in terms of rubrics! Now what ELSE can we make Greasemonkey do for us? 😉

James
Community Champion
Author

 @sbastian , glad you found it useful.

Once I got it figured out, I was amazed by the ease of it. It took me a while to get it working because I was working from the Greasemonkey docs that came up with a Google search. O'Reilly had an online book, but it was for version 0.5 and things have changed a lot since then (they're up to 3.3). Once I got the timing issues down -- I had to wait for that "editing" class to be added before attaching rowSorter() -- the other was really simple and I didn't have to mess with unsafeWindow at all like a lot of the online stuff said I would.

The "preferred" way for modern browsers seems to be MutationObserver Objects, but it wasn't as simple as the waitForKeyElements script.

As for what else Greasemonkey can do ... I think there are a lot of options: You're running code in your browser window like you're on the page. So you can simulate clicking on certain form elements to automate processes that take several steps, you can add buttons, you can change the CSS to stylize the page differently. You can add the tablesorter jquery library to the People page so that you can sort by any of the columns. On web pages that are paginated, like the list of pages, you can have it go ahead and automatically load the complete list of pages in the background rather than having to wait for you to scroll down for them to appear.

When I first started in the community, a lot of my responses were "You can't do that without modifying the global JavaScript file." Well, now you can -- except just for your instance. If you want to do it for everyone, you still need to modify the global JavaScript file. Then I switched to answering a lot of API questions and started writing some Google Spreadsheets to do stuff with the API. Then I started to run into "You can't do that with the API, you can only do that from within the web interface." Now that I've discovered Greasemonkey, I might be able to start answering those questions.

And if I could figure out how to access the clipboard, which seems to be a security risk so I may need to take a different approach, I would love to see the ability to take a Rubric from Excel and have it import into Canvas.

sbastian
Community Novice

Oh being able to take a Rubric from Excel into Canvas would be AMAZING! So many of my faculty already have rubrics created that they've used for years - the copying and pasting is tedious.

kona
Community Coach
Community Coach

I just went through the steps and you are right, it was super easy and quick to set-up. The best part though, actually testing it on a rubric and being able to rearrange the order of the rows any way I want them! Wow! I can't count the number of rubrics I've just deleted and started over because I didn't have the ability to reorder rows before! Thank you!

lane_worrall
Community Novice

This is wonderful  @James ​!  You're instructions are awesome!

I've created my script (in Chrome) but when I try move rows while editing a rubric nothing is happening.  Tampermonkey indicates that the script is enabled.

I opened Dev Tools in Chrome to see what's going on, and here's the screenshot of the error message I am seeing (I confirmed that the extension referenced here is in fact my Tampermonkey extension):

Screen Shot 2015-09-27 at 6.19.35 PM.png

Any thoughts on where I went wrong? 

James
Community Champion
Author

 @lane_worrall ​,

I had not tested that script on Chrome when I wrote it, but I did happen to update it over the weekend to not use the rowSorter.js script, but the jQuery UI sortable() function that's already loaded on the page by Canvas. It actually performs better on Firefox than before and it also works with Chrome and Tampermonkey.

I made it publicly available so you don't have to manually copy/paste the code and I named it with a .user.js extension so the user script managers will automatically detect it. If you have Tampermonkey installed and click the link below, it will show you the source code and ask if you want to install it.

I would remove the version you have and then try this one: https://github.com/jamesjonesmath/canvancement/raw/master/rubrics/sort-rubric/sort-rubric.user.js

I'm not quite ready to announce the site as I'm still working on it, but if you want to look around at other things, you can take the part before the "raw" in the URL go there.

lane_worrall
Community Novice

Worked like a charm!  Thanks so much! Smiley Happy

James
Community Champion
Author

Woohoo! That's what I like to hear.

When I originally developed the user scripts, I didn't test it with Chrome because I was just learning and the documentation was mostly for Firefox/Greasemonkey. Now that I've got several under my belt, I'm going back and fixing some others. The Roster Sorter is another one that I've got working on Chrome, but the PDF Roster and the Photo Roster still aren't. Part of the issue is that the libraries I include don't always work and that's what I found with the Roster Sorter. Once I changed libraries and the call it made, I didn't have to change any other code.

Stef_retired
Instructure Alumni
Instructure Alumni

Thanks,  @James ​, for creating this resource. I'm looking forward to trying it out, and have linked to it here: #paperpumpkin Rubrics!

James
Community Champion
Author

There is an easier to install version at Canvancement/rubrics​, which is the version I pointed Lane to on Sep 27, and that version works with Chrome as well as Firefox.

I just haven't had time to update this blog and make a new video, or to finish and announce the Canvancement site, but basically it boils down to 2 steps: 1) Install Grease/Tamper Monkey and 2) click on the script.

It's "Sorting Rubrics Made Super-Easy"

hauckc
Community Novice

Thanks for this. Unfortunately, neither version is working for me (the one you discuss in this post and the simpler one at Canvancement/rubrics). In both instances, it appears that the script is enabled for the page. I'm using Firefox. Any advice about how to troubleshoot this? Best wishes, Christina

James
Community Champion
Author

 @hauckc ​,

I just went and installed the script from Cavancement/Rubrics on my laptop with Firefox/GreaseMonkey and it worked.

Are you sure you're using it in the right place. You need to go into Outcomes > Manage Rubrics and edit it from there. It won't work if you try to edit it within an assignment. The URL should end with something like /courses/123/rubrics/456

Here's a screen shot of mine. The GreaseMonkey menu is over on the right. Notice it says Enabled and "Sort a Rubric" at the bottom.

132277_pastedImage_2.png

The other thing is that you have to click Edit Rubric before it will do anything.

If all of the above looks right, it might have something to do with a rubric used in more than one place or there might be something else going on that will take more thought.

hauckc
Community Novice

James,

Yes, I am getting to my rubric via outcomes/manage rubrics and I am in edit mode and greasemonkey is installed and the script is enabled.

Here is a picture of my rubric in edit mode:

Screen Shot 2015-11-20 at 12.49.50 PM.png

Here is a picture of your edited script:

Screen Shot 2015-11-20 at 12.52.47 PM.png

Maybe I need to talk to my tech people here.

Thanks,

Christina

James
Community Champion
Author

Don't hard-code the course number and the rubric number into your code. Use the *. You didn't need to hard-code k-state either. It should work out of the box

The first thing I would check is that your page says rubric 7138 but you've got 7183 in the code

hauckc
Community Novice

Installed the unedited code and Bingo! And, wow, I spent a lot of time looking at little bits of code today. (including the time I spent finding and correcting the rubric number error even before you pointed it out).

Thanks so much. This will make my life easier in so many ways.

Christina

James
Community Champion
Author

I'm glad you got it working and that I don't have to figure out how it broke.

For those stumbling across this thread, be sure to install the version from the Canvancement site rather than the version given in the original blog post: it's cleaner, works with Chrome, and doesn't need changed unless you're running a custom domain.

jen
Community Contributor

Will this work the same way in the new interface?

Thanks!

James
Community Champion
Author

Yes.

The new UI hasn't modified the contents of the individual pages, just the way they're displayed. To be sure, I did just verify this in our beta site using the new UI and it works.

Just make sure you install the latest version, not the one provided in the original source.

While testing, I noticed that if you edit, update, and then immediately edit again, the reordering drag-drop may not work. If you refresh/reload the page then it works again. That's a minor inconvenience that I probably won't fix.

nealc62
Community Member

James, You're my new hero! Canvas needs to implement this idea!!!

nealc62
Community Member

James, I just installed Tampermonkey Chrome extenstion and the js and it works exactly as you describe here in the new Canvas UI; nonetheless, very helpful!

mje
Community Novice

 @James  This is cool, thanks for sharing!

Would it be difficult to add a feature "copy current criteria to bottom"?

I find myself spending a lot of time, changing the number of columns for each criteria. If I could copy current criteria to bottom it would ease the work significantly. Copying criteria in general would help a lot. By example I have 3 criteria that applies to each sub question in an assignment. Today these have to be entered manually ... (not an efficient system).

James
Community Champion
Author

 @mje ​,

Difficult is a relative term, so I guess it depends on how well you code in JavaScript.

It's not something I'm interested in pursuing because there are people who have written complete systems that will import a rubric into Canvas for you. I think you use a spreadsheet to create it and then it creates the rubric from it. What you're talking about seems like it could be addressed by that much better than by this script.

As a point of disclosure, I needed to create a lengthy rubric recently, looked at their code, and decided it was easier for me to just go through and manually create it (and I'm the kind of person who hates repetitive processes). But I only had one rubric to create and someone who had a lot of rubrics to create might find it invaluable. Someone who has the information in a rubric somewhere else might find it useful as well so that they didn't have to recreate it inside Canvas.

The purpose of the sorting rubrics script isn't to be a powerful rubric editing tool. It was just meant to add sorting capabilities for people who want to rearrange the order of the terms.

But if you would like to have Canvas add this feature, you can search the Community to see if someone has already suggested it or something similar -- if not, you can add your own feature request.

mje
Community Novice

I was referring to your Javascript skills ;o) 

I have searched for the system you mention above, but without luck. Could you please point me to their site / code?

Kind regards,

Michael

James
Community Champion
Author

I believe it's this one unsupported-canvas/api/import_outcomes/python at master · kajigga/unsupported-canvas · GitHub

And now that I search, I see that it's about outcomes, which are related to rubrics, but I think that's what I was thinking of instead of rubrics. That makes sense because I had about 48 outcomes in my summer algebra course. It's been a few months and a lot has happened since then except for sleep. I believe I had seen something on Rubrics before, but I don't see it during a search right now.

I think searching in the Canvas Community is limited to groups you belong to, so things might show up when one user searches that don't show up for another. I actually used Google to search for it and added GitHub to the search terms to find it.

mje
Community Novice

What about a script roughly looking like this?

waitForKeyElements('.rubric_container.rubric.editing', attachImportRubrics);

function attachImportRubrics() {

// rough idea, non-working code below:

pseudo code: prompt user to open certain csv file (or just use a hardcoded pre-defined filename)

  // I could certainly live with some rough / hardcoded functionality here, it is a lot better than manually modifying rubrics.

pseudo code: open file, make sure it is readable.

var tableRef = $('.rubric_table tbody')

// loop#1 : loop around below code to insert rubric, row-by-row.

pseudo code: read one line from CSV file with rubric criteria (row-by-row)

var newRow = tableRef.insertRow(.tableRef.rows.length);

// loop#2 : loop around below for each criteria column

var newCell = newRow.insertCell(0);

pseudo code: extract (next unread) field in imported CSV line.

var newText = document.createTextNode('some text');  // insert field here instead of this.

  newCell.appendChild(newText)

// end loop #2.

// end loop #1.

}

James
Community Champion
Author

When I thought about adding this functionality myself, I thought a textbox that you could copy/paste the tab delimited rubric into would probably be the easiest way to go as pure JavaScript has issues reading local files and if you hard-code it, you severely limit the usability to be just you and not anyone else who might benefit.

You would need a predefined column order or headers that must be included. For a basic layout, you might do:

criteria, longdescription, points1, description 1, points2, description 2, ..., pointsk, descriptionk

That would be variable length since not every criteria has the same number of columns.

Then you have the option of making some of those tied to outcomes.

I have concerns over whether you would be able to just create new text fields and put in there, but that you'd have to invoke the button to add a new row before pasting information in there. What you would need to do snoop around in the inspector and see what extra classes and ids get added to the entries -- if any.

An alternative approach would be to use the network monitor and look at what information is actually sent to Canvas. Then your script might be able to create the payload needed to do that and invoke the call directly rather than trying to create it as a table first. That falls under the heading of "undocumented" and "unsupported", but it may work.

You should go over to the Canvas Developers​ group and ask about it there. Those people know a lot more about it than I do and some of them may have already done it. Unfortunately, I have too many other things going on right now and need to finish things, not start other ones.

James
Community Champion
Author

 @mje ‌,

I have a working beginning of a script that will do what I alluded to in the previous post. I flipped things around a little in the order and decided not to mess with outcomes in an effort to simplify it. You basically create the rubric in Excel and then (once finished) you'll paste the tab-delimited input into a textbox on a form and it will create the rubric for you. Nothing fancy, but then people could use the rubric sorter script if they need to move things around and they could edit it using Canvas' built-in tools if the need to attach outcomes. After talking with  @kona ‌, we came to the consensus that there were enough people who could benefit from that much of a tool that it was worth pursuing.

I posted a description of the current state of the code and a request for feedback before I finish it in another discussion: https://community.canvaslms.com/thread/14999-is-there-a-way-to-programmatically-create-and-edit-rubr... 

James
Community Champion
Author

I've written a companion script to this sorting roster script. It allows you to create a rubric using a spreadsheet and then copy/paste the rubric into Canvas. This new script will create the rubric and the script on this page helps with editing.

https://community.canvaslms.com/docs/DOC-8844-importing-rubrics-from-a-spreadsheet?sr=search&searchI...

jbuchner
Community Contributor

Alright, so why doesn't Canvas give you a sum of money, buying this idea from you, and just making it a feature of Canvas?

James
Community Champion
Author

There's nothing to buy, I open-sourced it.

The reasons are probably the same that lots of things don't make it into Canvas: doesn't fit with their vision, not enough people benefit, have something more awesome in mind, accessibility, not easy enough, requires technical skills or external programs, working on bigger things, etc.

gramos
Community Participant

Heart Thank you so much!

melissa_kamp
Community Participant

This is fantastic -- thank you!!

twassmer
Community Participant

Thanks a lot!

kmcgrath
Community Participant

Great... Thank you!

juhall
Community Explorer

The sorting rubrics script on tampermonkey is no longer working for me. 

It worked before, but now Tampermonkey will tell me I have no script assigned, even though in the dashboard the script is enabled. I've disabled and re-enabled it. I've reinstalled it. I refreshed google. Any thoughts for me?

It does say something about a $ not being defined - does that make a difference? (I know nothing about writing these scripts.)

blong
Community Participant

James, this was amazing work and the faculty that found out about it have loved it.  We've noticed that since the recent change in canvas, where rubrics are their own thing, tampermonkey or the script no longer allow us to rearrange the rubric items :(.  I am not receiving errors like the user above, none of us can get the rubrics to rearrange or even select as we could before.

I'll note that I have only tried in Chrome, I have not tried in firefox or edge.

Chris_Hofer
Community Coach
Community Coach

@blong ...

I just used James' script today to re-arrange rows in a few rubrics I had created for a course.  I was able to use his script in Chrome with Tampermonkey without issue.

blong
Community Participant

Weird, we haven't been able to get it to work at all :(.  I had 3 different people trying. 

*edited* I'm going through our custom code and re-pasting the script just in case something got deleted by accident.

klpoh
Community Novice

I just want to affirm that this script is working as of today. I was initially trying to edit a rubric while on the assignments page, where it didn't work. All I had to do was go to the course Rubrics page (https://canvas.instructure.com/courses/COURSEIDNUM/rubrics), go to the rubrics I wish to rearrange, and it worked fine dragging and dropping on that page.

James
Community Champion
Author

@klpoh 

You make a good point. Some people have commented on some of my other scripts about how it stopped working for them from the assignment page. In reality, it never worked from the assignments page; you always had to go the rubrics page. People have phantom memories or perhaps they project what they wish would happen onto what really does happen.

@blong 

The move of the rubrics to its own navigation menu didn't change anything about how rubrics worked, it just made it easier for people to get to (you don't have to go through outcomes anymore). It didn't change the URL, so the script should still work (as supported by other people's comments).

amcvey3
Community Member

Hi @James, I just installed this and it's working great! Is there a way to add code so that we can also sort the ratings columns? Sometimes when we import content from one LMS into Canvas, the rubric ratings are in ascending instead of descending order, and don't work properly for grading. I'd love to be able to drag and drop those columns to rearrange them.

Thanks!

James
Community Champion
Author

@amcvey3 

The way to change the order of the columns is to change the points assigned. Dragging them within the rubric would not accomplish anything because Canvas displays them in descending order based on points.

michelli
Community Explorer

Hi James

I'm always in awe of what you can do! Thank you for this script. It just saved me hours!

The_Viking
Community Participant

How this isn't built in is beyond comprehension.  Canvas should pay you to work for them! 

James
Community Champion
Author

@The_Viking 

A real solution from Instructure would have to be accessible, with handles from dragging and the ability to move items using only the keyboard.

Ron_Bowman
Community Champion

@James -

I was just using the rubric-sorter and came across an interesting issue(my operator error).  I am not sure if it is a bug, intentional design, or something that never came up before.  I have not tried duplicating it yet.

in the following screen grab

rubric-sort_mashup.jpg

 I had the top line for process vowel function and was adding in a copy of it for the process consonant function.  I had both criteria present, and on the consonant line I had corrected the wording for 0 points to state no function for processing consonants.  I wanted to copy that phrase, so I went to highlight the wording to copy it.  in doing so I inadvertently drug the mouse(or did something strange)  and I ended up with what you see.  I have tried to reproduce that effect, but have not had any luck in doing so.  

so somehow I managed to take all of the ratings for Process consonant function criteria and move them to the process vowel function criteria.

Any ideas?

Fortunately, I just saved the rubric and went in and deleted out all the extra ratings and the empty criteria and redid the copy of criteria.

Ron

James
Community Champion
Author

@Ron_Bowman 

People still use that script? I haven't looked at it in a long time, but it is possible that Canvas has changed their structure and I'm putting the drag on the wrong element. The script itself is pretty short, so that's about all I can think of that might be causing the problem. It is unlikely that they upgraded jQuery UI.

I just looked on my end and don't see where anything has changed in the underlying structure. It worked for me in simple usage. I'm still waiting for Canvas to remove the jQuery UI like they said they would 6 years ago. That will break it completely when that happens.

I experienced some wonkiness, not what you're describing, after clicking the +Criterion button. But it may have been more a case of if you Cancel and then Edit again, the script doesn't run at all (you would need to reload the page).

I also noticed that I could drag a criterion beneath the footer that allows you to add a criterion.

I'm going to pretend I'm the Canvas documentation. It does what it says, but if you use it in a non-documented way, the behavior is undefined.

Ron_Bowman
Community Champion

@James -

Thanks.  No big deal, it was just an interesting quirk that I can't duplicate.

Why wouldn't people still use this script?  I use it all the time to rearrange a rubric or modify the copy of one that has most of what I need for a new assignment.  For me it is an easy way to fix rubrics.  

Ron

NathanButlerNBC
Community Member

If anyone is interested, I was able to get a version of this script running directly in the Canvas custom theme.js file, so no need for tampermonkey.

I had issues with some situations where, if I didn't refresh the screen after editing the rubric, then clicking to edit/save again could add some weirdness to the behaviour of the table. The code that I added absolutely doesn't work 100%, but it has helped a bit. If anyone wants to take the code and improve it, please do (I'm taking the approach that I'll try to keep bugging the CSM team to get this functionality added to the Canvas codebase properly, rather than me spend more time fixing my bad code 😁)

The code below can be added to the Canvas theme custom JS file, and should:

  • add the "sortable" functionality that @James wrote to the rubric
  • add a light blue background colour to the rubric table rows, to visually indicate that the elements are sortable
  • also ignore the "Add Criterion" row from being sortable.
function attachRubricSorter() {
  console.log ('Running attachRubricSorter');
  // 'use strict';

  const pageRegex = new RegExp('^/courses/[0-9]+/rubrics/[0-9]+');
  if (!pageRegex.test(window.location.pathname)) {
    return;
  }

  const waitForEdit = (mutations, observer) => {
    const parent = document.getElementById('rubrics');
    const el = parent.querySelector('.rubric_container.rubric.editing');
    if (!el) {
      if (typeof observer === 'undefined') {
        const obs = new MutationObserver(waitForEdit);
        obs.observe(parent, {
          'childList' : true
        });
      }
      return;
    } else {
      if (typeof observer !== 'undefined') {
        observer.disconnect();
      }
      attachRowSorter();
      attachRowSorterRemover();
    }
  }

  const removeRowSorter = () => {
    // Add a delay because the follow doesn't seem to work on the rubric save
    setTimeout(() => {
      try {
        $('.rubric_table > tbody > .criterion').each(function(){$(this).css("backgroundColor","")});
      } catch {}
      try {
        $('.rubric_table > .ui-sortable').sortable("destroy");
      } catch {}
      waitForEdit();
    }, 1000)
  }

  const attachRowSorterRemover = () => {
    document.querySelector('button.Button.cancel_button').addEventListener("click",removeRowSorter, { once: true });
    document.querySelector('button.Button.save_button').addEventListener("click",removeRowSorter, { once: true });
  }

  const attachRowSorter = () => {
    $('.rubric_container.rubric.editing .rubric_table tbody').sortable({
      axis : 'y',
      containment : 'parent',
      items : '> tr:not(.summary)'
    });
    $('.rubric_table > .ui-sortable > .criterion').each(function(){$(this).css("backgroundColor","aliceblue")});
  }
  
  waitForEdit();
}

try {
  const pageRegex = new RegExp('^/courses/[0-9]+/rubrics/[0-9]+');
  if (pageRegex.test(window.location.pathname)) {
    attachRubricSorter();
  }
} catch (err) {
  console.log(err);
}