Register for InstructureCon25 • Passes include access to all sessions, the expo hall, entertainment and networking events, meals, and extraterrestrial encounters.
Found this content helpful? Log in or sign up to leave a like!
I am using a curriculum that uses the Canvas platform. It has an extra button for teacher resouces in the module view. How can I add something like this in my Canvas? See screenshot. Thank you!
@chrismhs ...
This looks like some custom code that the school has implemented into that Canvas environment. You could create a non-published page in your course that only you (as the instructor) would see. Students would never see the page. Then, you could put anything you want on that page...including links to instructor resources. Do you think that might be a workable solution for you?
Hey @chrismhs ,
I agree with @Chris_Hofer , this is something I have never seen before in a typical Canvas production environment. I thought I'd also tell you something that we've done in my classes in the past for teachers. I am a former computer science TA (teacher's assistant), and in our Canvas course we would have a module at the top called 'Teacher Resources'. That module, and all associated items within it, would always remain unpublished. That module would contain resources such as lesson plans, answer keys and the files to the unit exams. Then, we created another module with all the student assignments and resources and published everything in that module so the students could work through it at their own pace.
Do you think that would also be another possible solution for you, in addition to what Chris suggested above?
All the best!
Noah
Thanks for your suggestions. I have done the separate module before and understand how it would work. It just seemed optimal to have the corresponding lesson or info right there in the same module as the students, but not allowing them to access it. When you click on the button, it actually opens up a window along the side with relevant info and it is pretty cool. It is probably true that they did their own thing to create it.
Hi there, @chrismhs ...
A slight variation on @NoahBoswell's suggestion could be to create a hidden page in each of your modules instead of haivng a separate module that contained all your hidden pages that you didn't want students to see. In a module, you can publish just those items you want students to see and also keep one or more items hidden so that they are only accessible to the instructor. That way, you're not having to scroll to a certain area of your "Modules" page just to get to all hidden items.
I'm not sure if you've heard of Cidi Labs, but they have a product called DesignPLUS which really enhances courses with lots of different elements like banners, content blocks, and many other things. As part of that software, they have some elements that can be inserted into course pages that always remain hidden to students. So, within these hidden areas of a page, you could put info just for the instructor...for example, instructions on how to build a page of content .. or how to fill out a templated page. DesignPLUS is a paid add-on from Cidi Labs.
I hope this extra info will be of some help to you. Take care...be well.
This is an interesting concept. I'm going to take a different approach than others have suggested. In the end, you may decide their approach is easier to accomplish because it doesn't require anything special.
I'll offer a suggestion before I go into answering what you really asked about. If you want to keep the resource near the module item, then you could have the primary module item and then, right below it and indented a level (or two), have a link to the resource. This keeps the resource right next to the item as opposed to having it in a different module. The primary module item for the students needs to be published, but the ones for the teacher should remain unpublished.
As for actually adding a link to each module item ...
I checked the list of supported placements for external tools and do not see that location in any of them. That means that this is likely custom JavaScript that has been created that will add this. That custom JavaScript could point to an external system or it could point to pages within Canvas. However, custom JavaScript can only be installed at the [sub]account level, not at the course or user level (although people have suggested that there should be more flexibility). That means that a Canvas admin would have to install it and it would need to be for the entire account (or a subaccount). That's unlikely to happen unless a third-party vendor is supplying the solution.
The benefit of an external solution is that you can create a link -- using existing content on the modules page -- that will link to the external system and pass the module item ID. That external system could, if necessary, query Canvas to get information about the module item and present information when you click on it. If it has existing resources, it shows them to you and if not, it allows you to create them.
That external system is likely going to be a commercial solution. You will need to host the information on their systems and that takes resources. There may be open source solutions, but then you would need to set up a server to manage it and that takes resources. Your institution may be able to support that or they may not. None of those are solutions that an instructor can set up on their own without the help of IT and your Canvas admin.
Let me talk about something that you can do on your own, completely within Canvas.
We get around the inability to install a global custom JavaScript package through the theme editor by using userscripts. Userscripts are scripts ran in the browser for a particular user. They have to be installed using a userscript manager such as Tampermonkey. You, the user, control which browsers you install it in. If you're using a school computer, they may block userscripts (they can be used maliciously so it can be a security risk if you're not sure what you're running). Basically, it allows you to inject JavaScript into your page in addition to whatever JavaScript is already being loaded by the site. That can often be bypassed if you have a non-school computer.
Because it doesn't run for everyone, it doesn't slow other people down and poorly written code doesn't crash the whole system. I develop my code using userscripts and then may publish them for all of our users after I've worked out the kinks.
How could you implement this within Canvas.
It depends on how your resources are created, but the simplest way would be to have a resource that is named the same as your main module item but with an extra word, phrase, prefix, or suffix in the name. For example, if you have a published student page called "1.1 Introduction to Calculus" then you could have another, unpublished page, called "1.1 Introduction to Calculus Resources". Or you might name it "Resources: 1.1 Introduction to Calculus". It comes down to where they appear in the list of pages. With a suffix, it's sorted next to the regular item and with a prefix, all the pages occur in one place. You may want to use something like "ZZ: 1.1 Introduction to Calculus" just to put them all that the end. If you don't ever use content pages for the students, then you could make the entire content pages system be the resources system and just use the same name as the assignment.
When the modules page is loaded on a computer that has the userscript running, it could can the page and decide what to do with each item.
Some information comes preloaded with the page and is available for immediate access. Think about clicking on the + to add a module item and some is already there while others have to be loaded. The list of assignments, quizzes, pages, and discussions is immediately available. The list of files is loaded after you select File. That means that if you want to use content pages for your resources, this can be super-fast.
If your resources are files, it's going to be much slower, especially with a lot of files.
There is another potential reason for using content pages. You could create a link to a content page for every assignment, discussion, quiz, or content page without checking to see if it exists. Then, when you click on the button, it would allow you to create a new content page if it didn't already exist. This adds extra complexity and I don't really recommend it, although you could scan for the existing page and make your link go to a "create new page" if the page doesn't already exist.
Files as resources are not recommended for a couple of reasons. Not only do you have to load the list of files before you can create the link to them, but you won't be able to add a new file through this like you could with a new content page.
I'll move forward assuming that you want to use content pages. Again, this is not working code, just explaining what could be done.
You could get the information about the assignment (or other types) from the Document Object Model (DOM) using JavaScript. Take the title and look through the list of pages that was loaded for the + button and look for a match.
Here is some code to get the list of existing pages.
function getExistingPages() {
const items = [];
document.querySelectorAll('#wiki_pages_select select option').forEach(e => {
const item = {id:e.value, title:e.textContent};
items.push(item);
});
return items;
}
You can get a list of all the module items on the modules page with this code.
document.querySelectorAll('ul.context_module_items li.context_module_item');
Within each result is everything that Canvas shares about the module item.
Where is code that will take every module item (regardless of type) and look for an existing page with the same name but the word "Instructions" at the end. That's because that's how I name my resource pages so it's something I could test.
function updateModuleItems() {
const existingPages = getExistingPages();
document.querySelectorAll('ul.context_module_items li.context_module_item').forEach(mi => {
const title = mi.querySelector('div.module-item-title a.ig-title.title').getAttribute('title');
const resourceTitle = `${title} Instructions`;
const matchingPage = existingPages.find(e => e.title === resourceTitle);
if (matchingPage) {
// We have a match, need to do something with it
console.log(matchingPage);
}
});
}
That code just shows the matching pages, you still have to do something with it.
There is an element with CSS selector 'div.ig-admin' that will give you the right side where the published icon is. You could insert your icon with a link to the resource page as the first element there. Note that we don't have the URL to the page, but we do have the ID and pages can be accessed by ID. /courses/1234/pages/3456 is just as valid as /courses/1234/pages/backwards-elimination (assuming the ID for the backwards-elimination page is 3456).
Again, that's not a complete working example, but it gets you most of the way there. You still have to add code to make sure that it only runs on the modules page and to add the icons with links. But at least it's enough to see what might be involved in creating such a system and that can help you decide whether it's something you want to pursue or not.
Also note that the code wasn't fully debugged to see what happens if you rename a module item from the original name. I do that with files because "the_table.pdf" isn't as nice looking as "The Table!" but you can rename module items and you would have to decide whether you wanted to use the original name or the module item name.
Using files for resources adds a whole other level of complexity to the mix and slows things down as it loads the list of files. My course has lots of stuff in it: I had 323 module items, 187 pages, and 540 files. It already takes too long to load the modules page but it takes another couple of seconds to load the list of files. The modules page would display and then your script could start showing the icons for file resources after the couple of seconds has passed. With content pages, it would be nearly instantaneous once the modules themselves loaded.
Thanks everyone for your suggestions!
To interact with Panda Bot in the Instructure Community, you need to sign up or log in:
Sign In