How to List Items Alphabetically when Adding to a Module

James
Community Champion
6
13172

Update: August 26, 2017

This was one of my early works and before I learned how to package it to make it easy for people to use. I've repackaged it and made it act more like the other Canvancements I've written. The script still worked after these two years, so I didn't change it other than to make it easier to install and make sure it runs on the correct page.

Quick Install

Here are the quick install steps. It has been tested with Firefox and Chrome.

  1. Install a browser add-on: Greasemonkey for Firefox or Tampermonkey for Chrome/Safari
  2. Install the sort-content-selector user script.

This script intentionally does not run on the course Home page. You'll need to go to the Modules page to use it.

Original Post: August 26, 2015

Synopsis

When a user clicks on the Add Items to a module, the order of the pages is inconsistent. Some items are listed in order of most recent edit and others are listed alphabetically. This can make it difficult to find items. This post will show you how to add a script that will sort those lists alphabetically for you.

Introduction

This issue may not be as popular as the one addressed by Sorting Rubrics Made Easy , but it will help demonstrate some of what can be done with Greasemonkey and injecting your own user scripts onto a page.

 @Chris_Hofer  created a feature request   that managed to get a whole 4 votes in the three months it was open for voting. After that one had been archived,  @epokryfki  created a feature request that basically asked for the same thing. Deactivated user suggested the two of them collaborate and come up with a compelling description.

Here is a short 55 second video demonstrating the problem and the proposed solution.

Instructions

Installing Greasemonkey

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 short video on how to install Greasemonkey and start your first script.

Creating a Script

Make sure you have enabled Greasemonkey. Then go to New User Script.

Hint: Greasemonkey will automatically attempt to use the name of the page you're on, so you might want to navigate to the proper page before you create it.

Complete the configuration form.

  • Name: Give it a name to identify the script
  • Namespace: This is a URL or URI to identify the author, just in case two people have the same name for a script. There are collections of user scripts out there. I'm not publishing this one to those places because the include pages need configured before they are useful.
  • Description: A brief description of what the script does
  • Includes: This is a list of the pages where you want the script to run. My Canvas instance is https://richland.instructure.com and I want it to run on the modules page (but not the homepage). So I put https://richland.instructure.com/courses/*/modules. The * is a wildcard so that it matches the modules page on any course. I also added https://richland.*,instructure.com/courses/*/modules so that it will run on the test and beta instances as well. This part absolutely needs customized for your site!

sort_add_item_config.png

Then click OK and you'll be given an editor. Paste the code below into the editor. Note that you may want to start after the header so that you don't wipe out the work you just did.

Note, this code is also available as an attachment to this post.

// ==UserScript==
// @name        Canvas Sort Module Add Item
// @namespace  
https://people.richland.edu/james

// @description Alphabetically sort the Add Items to a Module lists
// @include    
https://richland.instructure.com/courses/*/modules

// @include    
https://richland.*.instructure.com/courses/*/
modules

// @version     1
// @grant       none
// ==/UserScript==
var itemTypes = [
  'assignments',
  'discussion_topics',
  'wiki_pages',
  'quizs'
];
for (var i = 0; i < itemTypes.length; i++) {
  var sel = '#' + itemTypes[i] + '_select select.module_item_select';
  if ($(sel + ' optgroup').length > 0) {
    sel += ' optgroup';
  }
  console.log(sel);
  $(sel).each(function () {
    sortOptions($(this));
  });
}
function sortOptions(j) {
  var newRegex = new RegExp('^\\[ New');
  var numRegex = new RegExp('^([^0-9]*)([0-9.]+)');
  var options = $(j).children('option');
  if (options.length > 0) {
    options.sort(function (a, b) {
      var atxt = a.text;
      var btxt = b.text;
      if (newRegex.test(atxt)) {
        return - 1;
      }
      if (newRegex.test(btxt)) {
        return 1;
      }
      var anum = numRegex.exec(atxt);
      var bnum = numRegex.exec(btxt);
      if (anum && bnum && anum[1] == bnum[1]) {
        return parseFloat(anum[2]) > parseFloat(bnum[2]) ? 1 : - 1;
      }
      return atxt.localeCompare(btxt);
    });
    $(j).empty().append(options);
  }
}

Then click Save and enjoy alphabetically sorted lists when you add items on the modules page.

If you need to edit the code and you're on one of the included pages, just open up the Greasemonkey menu and right click on the script name at the bottom. If you're not on that page, then you can go to Manage User Scripts and right click on the script there.

Explanation of Code (Optional)

There are no additional JavaScript libraries needed to run this as jQuery comes with every page in Canvas.

  • Lines 1-9 are the Greasemonkey configuration. Be sure you change the @include statements on line 5 and 6 to match your site. The second one in line 6 is optional if you don't want to use this in your test or beta site.
  • Lines 10-15 specify which types of items to sort. You'll notice that attachments (files) is not included. It is loaded by AJAX calls when you first click on it. The others are all loaded ahead of time. Quizzes were already sorted alphabetically, but I included them anyway.
  • Lines 16-25 iterate through the types of items to sort. It looks for a "optgroup", which is HTML-speak for a grouped item. In particular, the assignments list is that way. It does not change the order of the groups, so those will still be in the order they are on the assignments page, but it will sort the items within the groups.
  • Lines 26-49 does the sorting. It makes sure that any "[ New" type item remains at the top. Then it looks for text that contains a number. The sorting is done by comparing two items at a time, and if both entries contain a number and the part before the numbers are identical, then it will sort by the number rather than alphabetically. The normal alphabetical sort puts "Item 12" before "Item 2" and this keeps it in the proper order. It doesn't handle decimals with more than one decimal place, so if you have "Section 3.12", it will appear before "Section 3.2". I didn't want to overly complicate the code, because the idea of major.minor.minor numbering could go on forever. The comparison uses the localeCompare() function, so if you have accents or multinational characters, it should properly sort. When it's all done, it wipes out the existing options and then replaces it with the sorted ones.

User Scripts

Greasemonkey and User Scripts have the potential to provide interim solutions for a lot of feature requests. They allow you to do some things that would normally require access to the Global JavaScript file. One major benefit is that anyone can run user scripts, not just administrators. Another is that you can decide what you want to do, so if one instructor wants the items sorted alphabetically and another doesn't, then that's doable. With the Global JavaScript file, that's not an option.

You also get to manage the scripts separately rather than one large JavaScript file. If you need to include other libraries, that can usually be done by adding a single @require statement to the configuration in the heading. All GitHub hosted JavaScript files can be loaded through a content distribution network (CDN) so that you don't even have to host it yourself. And if you want to do something that requires a newer version of jQuery than the 1.7.2 that ships with Canvas, you can load that as well (usually this isn't needed).

The important thing to remember is that User Scripts do not run for anyone other than you and they only run on the pages you tell them to run on. That means that you cannot insert JavaScript that will do anything for anyone else, like embed a video or show a tweet. If you are asking a question like, "Can I use this so that the students will ..." the answer is "no!". But if you're designing a course, they can provide some added or improved functionality to make your workflow faster.

If you have Firefox sync enabled, you can sync your Greasemonkey scripts with your other computers.

6 Comments
kona
Community Coach
Community Coach

The directions initially sounded a bit tricky, but it was actually super easy to install and set this up. The only thing I noticed is that if you have your course Modules set as your home page this doesn't work (because you specified it to only work on the actual "modules" URL). This threw me for a minute, but as soon as I went to the actual Modules page (clicked on the Modules navigational link on the left) this worked BEAUTIFULLY!!

Thank you! This is going to be a HUGE time saver, especially in courses with a lot of content!

James
Community Champion
Author

 @kona ​,

I purposefully didn't do it on the main page because you might accidentally end up doing it on every page if you're not careful. It wouldn't necessarily harm things, but it would put a likely-trivial performance hit on every page and may have undetermined consequences.

// @include https://richland.instructure.com/courses/*

     will run on every page that starts off with courses followed by a number (a lot of them), not just the course homepage

// @include https://richland.instructure.com/courses

     will run on just the just the list of courses but not on any of the course homepages.

If you want it to run on the course homepage (realize this may not be the same for everyone but I use the modules page) but not on any other page then you would need to use a Regular Expression (of sorts) to specify that like this.

// @include /^https://richland\.instructure\.com/courses/[0-9]+$/

This is your user script, so you have the page set up, but I figured you actually want it to run on the modules page, not the homepage. Then it gives someone the ability to edit without the alphabetizing (from the home page) or with it (from the modules page)

nealc62
Community Member

James,

Wonderful creation!

Thanks,

Jan

englu061
Community Participant

Just came across this helpful idea and cannot wait to try it out. Thanks  @James ‌ for your work on this! I have been struggling to find/add pages when building modules.

James
Community Champion
Author

Let me know if it still works, I haven't tried it recently and Canvas has made some changes to things.

micek12
Community Member

Is there an update to this script for current Canvas?  I have a number of assignments in multiple modules that are not in order and I have to manually sort them.