@mjennings
There are a couple of routes I could go with this. I don't know your exact layout, but I'm going to start by assuming you are using @danielcktan 's post from April 30, 2019.
Step 4 says
Copy the JS code (jquery-ui.js) and Initiation code (below) required for JQuery UI Accordion to the Custom Javascript before uploading the file to the Theme Editor.
If you have copied the JS code from the jquery-ui.js file into your custom global JavaScript, make sure that your $().accordion() call is after it. I don't know how you have it loaded, but if you use var to define jQuery UI, then the function is hoisted to the top of the file and the order doesn't matter. If you use const or let, then the order matters.
If you copy/paste the jQuery UI code directly from the file, as Daniel said, then it's using an IIFE and gets invoked immediately. However, the $(document).ready() is also an IIFE because the document is ready before it ever gets to your code. Placing your code after the code that loads the accordion code should make the accordion code available. I'm not 100% sure on this as the jQuery UI code as an IIFE that has another function after the factory call, but if your code is before the jQuery UI code, then definitely make the accordion portion from jQuery UI come before anything that references it.
The second thought is the one I went to first, so I'll continue like I didn't even write the first part.
I can't say for sure, but this sounds like the issue that has been biting people for about a month since the October 2019 release. Part of their optimization involves changing the order scripts are loaded in so things that you think were available may not be available when you want to use them anymore. For my user scripts, it completely broke things that relied on jQuery. Those aren't supported by Canvas, so I had to not rely on my own versions. They have said that jQuery will be available before your user scripts are ran, but I cannot verify this because we don't have any custom global JavaScript using jQuery.
What's happening is that your document is ready before your other scripts have loaded. You will note that none of my code uses $(document).ready(). That's because Canvas promised us that the jQuery would be available when the document was ready, so it was a redundant check. Now, with the optimization, it's downright dangerous. The document is ready before most of the scripts have been loaded. That means that much of the content that Canvas dynamically generates has not been generated with the content is ready.
If you have to have accordions, a safer approach would be to load the jQuery UI to get the Accordion and then launch it after the script has been loaded, rather than when the document is ready. This also has the benefit (this is arguable) of not having to load the jQuery accordion code on every single page. Yes, it's cached, but you could decide to load it only on content pages and save some space in the custom global JavaScript.
If you're dynamically loading the Jquery UI code, rather than including it in the custom JavaScript, then it may not have loaded before you try to invoke it. In this case, you might want to make the launch of your accordion code depend be part of the .success() or .complete() portion of the code that loads the script.
I used to use the jQuery getScript function to do this, but I recently read that wasn't the best way. Now what I do is check to see if the function (accordion for you) exists and if not load it.
This code is untested with accordions, but it's based on some of the modifications I had to make after October 2019 to get my scripts working.
What it does is check for the existence of the accordion function before it tries to execute it. If it's not there, it loads it and once it's loaded, then runs the code to do the activate them. If it already exists, then it skips the loading and just activates it.
(function() {
'use strict';
if (typeof jQuery.fn.accordion === 'undefined') {
const script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/jquery-ui@1.12.1/ui/widgets/accordion.min.js';
script.onload = function() {
activateAccordions();
};
document.head.appendChild(script);
} else {
activateAccordions();
}
function activateAccordions() {
$('.enhanceable_content.accordion').accordion({
heightStyle : "content",
autoHeight : false,
collapsible : true,
active : false
});
}
})();
If you only wanted to run it on content pages, then you could insert this code after the 'use strict'; line.
if (!/^courses\/\d+\/pages/.test(window.location.pathname)) {
return;
}
A third possibility is that jQuery itself isn't available. If that's the case, then things get harder still. That would, at least at this stage, be a support issue as they've said that it will be or that they'll let us know before they remove jQuery.
If jQuery is loaded, but jQuery UI isn't loaded yet, then the example code should load it, but then you may have Canvas code come back and override parts of it. In this case, you could use the code above, but change the script.src line to use the jQuery UI distribution package rather than picking out just the accordions from jQuery UI.
In the meantime, a really quick way to get your code back up and running with the accordions if they're unavailable is to wrap your call in a check to make sure the accordion is available. For example, like this:
if (typeof jQuery.fn.accordion === 'function') {
$('.enhanceable_content.accordion').accordion({
heightStyle : "content",
autoHeight : false,
collapsible : true,
active : false
});
}