To Our Amazing Educators Everywhere,
Happy Teacher Appreciation Week!
I have been using Canvas a long time and in several of my classes, I have quizzes (or more accurately "exams") that have dozens of questions, many with mixed question types (e.g. multiple-choice, true/false, matching, short answer, and essay). Canvas can automatically grade the multiple-choice, true/false and matching questions, but the short answer questions and essay questions are harder. For the short answer questions, I have tried to come up with all the possible answers I think students will write, but I always get a student who gives an answer that is correct but not EXACTLY the way I worded it, or they misspell their answer, which causes Canvas to mark it as incorrect. For the essay questions, those are never graded and I have to review them. This means that I am scrolling through the dozens of questions for EACH submission to find the ones that need review. Canvas provides a box at the top with links to the essay questions ONLY, but if I click on one of those links, then the box goes away and I have to scroll all the way back to the top of the quiz to access it. Very time-consuming and frankly annoying, am I right?
Links to essay questions ONLY . Once you click on one link, it scrolls and you have to scroll all the way back to the top in order to access the next link.
Several years ago I read this post by James Jones about how to insert JavaScript into Canvas pages to allow things like sorting rubrics. Based on his script and some of my own research and expertise, I created a script that adds buttons to the Speed Grader that lets you jump to each question that is marked incorrect that is NOT a multiple-choice, true/false, or matching question. This has saved me a ton of time in grading my own quizzes so I want to share.
You can read more at James Jones' post, but this method involves installing a browser extension that manages "user scripts". The extension allows you to install scripts that can modify pages you are viewing in the browser it is installed in. The scripts have a line in them that tells the script to run only on URLs that match what is in the script, so it will only load the scripts for pages that match that URL pattern.
Tampermonkey is one of those "user script" extensions for Chrome. Greasemonkey is another one for Firefox. There are probably others, but those two are the most common.
This video shows how to install Tampermonkey:
Once you have Tampermonkey installed, you can install the script file.
The code should work on any Canvas installations that are hosted by Instructure, so if you are using Canvas through your university or school and the URL for canvas is something like "my_university.instructure.com" you don't need to edit anything else. If your university uses a different domain, you may need to edit the script file so it works with your domain.
At the top of the script you will see:
// ==UserScript==
// @Name Scroll a Quiz
// @namespace https://github.com/justinshewell/canvas
// @description This program allows the user to quickly scroll to quiz items that need review
// @include https://*.instructure.com/courses/*/gradebook/speed_grader*
// @version 1
// @grant none
// ==/UserScript==
To change the URL that the script works with, change "https://*.instructure.com/" to match your required domain name.
Here is the entire script with an explanation:
// ==UserScript==
// @Name Scroll a Quiz
// @namespace https://github.com/justinshewell/canvas
// @description This program allows the user to quickly scroll to quiz items that need review
// @include https://*.instructure.com/courses/*/gradebook/speed_grader*
// @version 1
// @grant none
// ==/UserScript==
(function() {
'use strict';
const pageRegex = new RegExp('^/courses/[0-9]+/gradebook/speed_grader');
if (!pageRegex.test(window.location.pathname)) {
return;
}
var observer = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
[].filter.call(mutation.addedNodes, function (node) {
return node.nodeName == 'IFRAME';
}).forEach(function (node) {
node.addEventListener('load', function (e) {
console.log('loaded: ' + node.src);
addScrollButtons();
});
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
function addScrollButtons() {
$.widget('ui.dialog', $.extend({}, $.ui.dialog.prototype, {
_title: function(title) {
var $title = this.options.title || ' '
if( ('titleIsHtml' in this.options) && this.options.titleIsHtml == true )
title.html($title);
else title.text($title);
}
}));
$('#justin-buttons').remove();
$('body').append('<div id="justin-buttons" data-qnum="-1"><small>Click the title bar above to drag this box anywhere on the screen.<br><br>These buttons scroll to questions that are marked incorrect or ungraded that are not multiple-choice, true/false, or matching questions, allowing you to easily review questions for grading without having to scroll yourself.</small><p style="text-align: center; margin-top: 20px;"><button id="justin-first" disabled><< First</button> <button id="justin-previous" disabled>< Previous</button> <button id="justin-next">Next ></button> <button id="justin-last">Last >></button></p></div>');
$('#justin-buttons').dialog({
height: 240,
width: 450,
title: 'Scroll Quiz Questions',
titleIsHtml: true,
resizable: true,
draggable: true,
dialogClass: 'alertDialog',
modal: false,
show: {
effect: 'shake',
duration: 1000
}
});
$('#justin-first').on('click', function() {
var iframe = $('#speedgrader_iframe');
var curQuestion = 0;
var top = $(iframe).contents().find('.question:not(.matching_question, .multiple_choice_question, .true_false_question, .correct)').first().offset().top;
$(iframe).contents().children().animate({scrollTop: top}, 500);
$('#justin-next, #justin-last').prop('disabled', false);
$('#justin-previous, #justin-first').prop('disabled', true);
$('#justin-buttons').attr('data-qnum', curQuestion);
});
$('#justin-next').on('click', function() {
var iframe = $('#speedgrader_iframe');
var curQuestion = $('#justin-buttons').attr('data-qnum');
console.log(curQuestion);
var els = $(iframe).contents().find('.question:not(.matching_question, .multiple_choice_question, .true_false_question, .correct)');
console.log(els);
curQuestion++;
if(curQuestion >= els.length) return false;
if(curQuestion > 0) $('#justin-first, #justin-previous').prop('disabled', false);
if(curQuestion == els.length - 1) $('#justin-next, #justin-last').prop('disabled', true);
var top = $(els[curQuestion]).offset().top;
console.log(top);
$(iframe).contents().children().animate({scrollTop: top}, 500);
$('#justin-buttons').attr('data-qnum', curQuestion);
});
$('#justin-previous').on('click', function() {
var iframe = $('#speedgrader_iframe');
var curQuestion = $('#justin-buttons').attr('data-qnum');
var els = $(iframe).contents().find('.question:not(.matching_question, .multiple_choice_question, .true_false_question, .correct)');
curQuestion--;
if(curQuestion < 0) return false;
if(curQuestion == 0) $('#justin-first, #justin-previous').prop('disabled', true);
if(curQuestion < els.length - 1) $('#justin-next, #justin-last').prop('disabled', false);
var top = $(els[curQuestion]).offset().top;
$(iframe).contents().children().animate({scrollTop: top}, 500);
$('#justin-buttons').attr('data-qnum', curQuestion);
});
$('#justin-last').on('click', function() {
var iframe = $('#speedgrader_iframe');
var els = $(iframe).contents().find('.question:not(.matching_question, .multiple_choice_question, .true_false_question, .correct)');
var curQuestion = $('#justin-buttons').attr('data-qnum');
curQuestion = els.length - 1;
var top = $(els[curQuestion]).offset().top;
$(iframe).contents().children().animate({scrollTop: top}, 500);
$('#justin-buttons').attr('data-qnum', curQuestion);
$('#justin-next, #justin-last').prop('disabled', true);
$('#justin-previous, #justin-first').prop('disabled', false);
});
}
})();
The first part, between the //==Userscript== lines is where the "user script" options are set. You should only need to change the domain as explained above.
The next few lines check the web address you are currently visiting to see if it matches the given pattern. If it doesn't, the script stops.
The next few lines set up an "observer" that looks to see if the Speed Grader content frame is loaded. If the frame is not loaded and we try to add features to the page, we will get errors, so we have to wait until the Speed Grader content frame is loaded. If the observer sees the frame is loaded, it runs the next part of the script.
The "addScrollButtons" function adds a "dialog" box with 4 buttons to the page:
You can click and drag the dialog box wherever you want on the window. To jump to quiz questions, click on the appropriate buttons. When you finish grading one student's submission and move to the next one, the buttons reset.
Enjoy!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Justin Shewell has a PhD in educational technology, and a master’s degree in TESOL with a bachelor’s degree in TESOL Education. Dr. Shewell is passionate about language learning and teaching, and has worked with teachers from around the world, most recently in Morocco and Saudi Arabia as an English Language Specialist sponsored by the US Department of State. Dr. Shewell is also passionate about online education, and considers it his mission to produce courses that are not only fun, but increase learning retention and transfer to the real world. He is the co-designer of the award-winning online TESOL certificate course Teach English Now! and the popular Learning How to Learn a Language. Dr. Shewell is also the creator of the Perception of Spoken Englilsh (POSE) Test, the one-of-a-kind perception diagnostic test for English learners and eslactivities.com. Dr. Shewell has written several articles and books, including 50 Ways to Teach Online, and 50 Ways to Learn a Language. Dr. Shewell and his family have lived in Hawaii, South Korea, the United Arab Emirates, and the United States, spending the last few years in Arizona. Photo credit: Alexandra Shewell
To participate in the Instructure Community, you need to sign up or log in:
Sign In