cancel
Showing results for 
Search instead for 
Did you mean: 
Nick_Yamagata
Community Participant

Accordion Script Help

Jump to solution

Our designers have developed some accordion scripts for instructors to use in their courses. We recently updated the script when jquery was disabled, things were going swimmingly with the new script until the 6-22 update last weekend.

 

A quick dump of our code here:
//Global Javascript

let accordion = document.getElementsByClassName("accordion");
let i;

for (i = 0; i < accordion.length; i++) {
  accordion[i].addEventListener("click", function() {
    this.classList.toggle("active");
    let panel = this.nextElementSibling;
    if (panel.style.maxHeight){
      panel.style.maxHeight = null;
    } else {
      panel.style.maxHeight = panel.scrollHeight + "px";
    } 
  });
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
/*Global CSS classes*/

.accordion:hover,.active {
    background-color: #e8e8e8
}

.accordionPanel {
    padding: 0 1em;
    background-color: #fff;
    max-height: 0;
    overflow: hidden;
    transition: max-height .2s ease-out
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
<!-- In Course HTML use -->
<h2 class="accordion">Heading 1</h2>
<div class="accordionPanel">
  <p>Heading 1 content goes between the div tags.</p>
</div>
<h2 class="accordion">Heading 2</h2>
<div class="accordionPanel">
  <p>Heading 2 content goes between the div tags.</p>
</div>
<h2 class="accordion">Heading 3</h2>
<div class="accordionPanel">
  <p>Heading 3 content goes between the div tags.</p>
</div>‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

 

I've done some inspecting and I wouldn't say I am a javascript pro, but I know I can F12 and look at how the page is applying the styles and watch the javascript in action, it doesn't seem to be detecting the mouse click to toggle the active attribute, but it does detect :hover. The strangest thing by far is that our accordion code still works totally fine everywhere except user created Pages (that is, with as deep as my testing has gone so far).

 

Does anyone else use accordions in your Canvas environments or similar CSS Javascript and are you seeing the same issue? Is there anything I might be missing in our javascript, or suggestions on working code?

Labels (1)
Tags (1)
1 Solution

Accepted Solutions
Nick_Yamagata
Community Participant

Aha! Canvas Support to the rescue. At first they thought it was the depreciated JQuery that was the source of my JavaScript woes. After clarifying that we were not using the JQuery library anymore, they were able to do some more digging and find that there was a change in JavaScript loading sequences. Some other developers have discovered this as well: How to adapt to the undocumented JavaScript loading sequence changes?

One of the undocumented 6-22 changes was with the order of what loads on the page. JavaScript used to load last, now it loads first. Our accordion code looks for elements with the class "accordion" on the page, so if JS loads before the HTML classes are there, there are no elements to get. With that knowledge, I changed my code to wait for the page to load before running:

window.onload = function() {    //loads with page to account for Canvas loading JS first
let accordion = document.getElementsByClassName("accordion");
let i;

for (i = 0; i < accordion.length; i++) {
accordion[i].addEventListener("click", function() {
this.classList.toggle("active");
let panel = this.nextElementSibling;
if (panel.style.maxHeight){
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + "px";
}
});
}
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

I understand that this fix means the script will not run until the whole page has loaded (after every other script has finished and every image renders). So there is a potential that our accordions will not work while a large image completes rendering, but this will be a good quick fix until we figure out a good setInterval() solution.

No JQuery necessary!

View solution in original post

0 Kudos
4 Replies
Boekenoogen
Community Contributor

We added this code to our .js file and it fixed the issue.

That looks like a great jQuery solution, but Instructure has pulled jQuery support from our Canvas environment so this code would be stripped on the front end. We had been using jQuery before, but had to switch to this setup.

I know they are ending that support in phases so it might not have affected your Canvas quite yet, unless you host your own jQuery library on your end? If you're hosting your own library or pulling from a separate host, do you see any substantial increase in page load times?

So what we have done is the following:

1. the code I posted is sitting in an open Google Drive Folder.

2. We added the following code to our Canvas js

// jquery-ui_accordion_only.min.js $.getScript('https://drive.google.com/uc?export=download&id=your google code here', function() {     //script is loaded and executed put your dependent JS here          // syllabus_accordion.js     $.getScript('https://drive.google.com/uc?export=download&id=your google code here', function() {         //script is loaded and executed put your dependent JS here     }); });

So we set up the process to only load the accordin js after the jquery is loaded.

I hope this helps.
Nick_Yamagata
Community Participant

Aha! Canvas Support to the rescue. At first they thought it was the depreciated JQuery that was the source of my JavaScript woes. After clarifying that we were not using the JQuery library anymore, they were able to do some more digging and find that there was a change in JavaScript loading sequences. Some other developers have discovered this as well: How to adapt to the undocumented JavaScript loading sequence changes?

One of the undocumented 6-22 changes was with the order of what loads on the page. JavaScript used to load last, now it loads first. Our accordion code looks for elements with the class "accordion" on the page, so if JS loads before the HTML classes are there, there are no elements to get. With that knowledge, I changed my code to wait for the page to load before running:

window.onload = function() {    //loads with page to account for Canvas loading JS first
let accordion = document.getElementsByClassName("accordion");
let i;

for (i = 0; i < accordion.length; i++) {
accordion[i].addEventListener("click", function() {
this.classList.toggle("active");
let panel = this.nextElementSibling;
if (panel.style.maxHeight){
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + "px";
}
});
}
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

I understand that this fix means the script will not run until the whole page has loaded (after every other script has finished and every image renders). So there is a potential that our accordions will not work while a large image completes rendering, but this will be a good quick fix until we figure out a good setInterval() solution.

No JQuery necessary!

View solution in original post

0 Kudos