After an outage on September 1, the Instructure Community is now fully available, including guides, release notes, forums, and groups. If some styling still looks unusual, clear your cache and cookies.
Found this content helpful? Log in or sign up to leave a like!
Hi, all.
I have been trying for literal weeks to get JavaScript to fire in Canvas using event listeners -- no taboo HTML tags -- and I can't seem to get it to work. The JS works fabulously on other servers, but something about the way Canvas calls it is throwing an error that the properties haven't loaded. (For those who are Canvas admins, you can see the page here. ) You can see the working code on one of my non-canvas servers here. Really basic stuff.
The Canvas response is: "The issue is the custom theme is loading before your wiki page and by the time the page is loaded the DOMContentLoaded event has already fired so you're always going to get the message
'Element with class "a.helloWorld" not found.' The method you're current trying to implement to trigger JS on your wiki page waiting for the DOMContentLoaded event isn't going to be reliable and I'd suggest investigating other options for finding your elements and setting up your listeners for your page."
The JS fires from the same subaccount as the course. There is no other JS that loads before it in upper subaccounts, and no other apps running anywhere.
I have tried with and without DOMContentLoaded, and I really have no idea how to get a simple event listener working. The JS is really very simple.
How, in Canvas, using the Theme Editor to hold your .js, can you use an event listener?
If you don't want to mess with my code, I'll even take a piece of code using an event listener that you know works in your instance. Something super simple, like with tabs or even an alert.
Solved! Go to Solution.
Instead of using DOMContentLoaded, you could try checking if the window is loaded.
window.addEventListener("load", () => {
// Do stuff
});
You could also set-up a MutationObserver. This should provide the quickest update once the detected content is loaded, but it is also more complex to set-up.
The Best Practices for Using Global JavaScript InstructureCon 2013 presentation also has an example of an onElementRendered function you could use to continue to check for an element and then do something once it finds it or stops trying after a certain number of attempts>
Instead of using DOMContentLoaded, you could try checking if the window is loaded.
window.addEventListener("load", () => {
// Do stuff
});
You could also set-up a MutationObserver. This should provide the quickest update once the detected content is loaded, but it is also more complex to set-up.
The Best Practices for Using Global JavaScript InstructureCon 2013 presentation also has an example of an onElementRendered function you could use to continue to check for an element and then do something once it finds it or stops trying after a certain number of attempts>
James you are wonderful, that is exactly what I implemented. However, now I'm running into a CORS policy error and I and my organization are not making any API calls, and we've deleted all of the apps from our account and all other JS from all the subaccounts above this to the top level.
So it's a separate issue, but do you have any insight?
Support basically told me to ignore all errors that have to do with "sentry.insops.net"... I think it's providing some internal analytic info to Instructure, but must get overloaded pretty often so comes up with weird errors. They said the operation of that server is not essential to Canvas functioning correctly. I really feel like they should address the core issue, as I hate having errors in my console while trying to debug my own stuff, but it's probably quite low on the priority list at this point.
-Chris
So Canvas just told me this:
Both the windows.onload and the DOMContentLoaded are firing before you're page loads and those implementations aren't going to be a reliable way to setup your listeners.
My code works fine when it's called, but it's not getting called.
You can try adding in an alert at the start of what your code does on window load. This can let you see if the function is ever called and what the state of the web page looks like at that point.
I have sometimes noticed that some elements will be fully rendered and then after it finishes loading some additional scripts for some reason it replaces the existing elements. So your script may be adding the elements in the initial load and then getting deleted when it updates the page again with new elements.
To handle this you may need to use a MutationObserver to watch and see if the elements are being replaced so you can add the content again. Alternatively, you could try making a helper function similar to the onElementRendered function that will keep checking after it added for a certain number of attempts in case it gets added and then removed while the page is fully loading.
While testing you could try using the setTimeout function just see if you can get the content to load after like 5 seconds. This wouldn't be the best approach for a production release due to variability in how long a page takes to load, but can help with testing just to see if you can get it to load.
A mutation observer is your most reliable option here, even though it is more complicated to set up than some of the other options. Canvas uses React to render the UI and Webpack to bundle the page content in smaller chunks of code that are asynchronously loaded in the browser, so you cannot trust the DOM (because React may change it at any moment) or the document "DOMContentLoaded" event (because the event may fire before all the JS code chunks have loaded).
The window "load" event could work, but it will prevent your JS from firing until the entire page is loaded, which could result in a noticeable delay between the time the window "load" event fires and the elements your JS wants to modify are loaded in the DOM. To the user, this results in seeing one thing load in Canvas and then suddenly change. You really want your code to know when your targeted elements are loaded as soon as possible to prevent this.
A mutation observer will let your JS watch for changes and the moment the target element is identified, it can run the rest of your code. This also lets you handle instances where React re-renders an area of the page. You may or may not need to watch out for React renders based on where you want to make modifications. JavaScript.info has a good overview of the MutationObserver that you may want to review to learn how it functions. Depending on what you want to do, you may consider setting up an observer on the <body> tag until the <div id="content" class="ic-Layout-contentMain" role="main"> tag loads (this is the parent tag of the content on a page, assignment, discussion, etc.). Then you can disconnect the MutationObserver on the body tag and set a new MutationObserver on that <div>. The reason why you may want to do this is that the MutationObserver can end up slowing your page down, especially if you use the "subtree" option, so you really only want it observing only the elements who's changes your code needs to know about.
To interact with Panda Bot, our automated chatbot, you need to sign up or log in:
Sign inTo interact with Panda Bot, our automated chatbot, you need to sign up or log in:
Sign in