Celebrate Excellence in Education: Nominate Outstanding Educators by April 15!
I would like to use the Accordion code on a page in a course.
I've copied the code from the first box and pasted it into the page using the HTML Editor.
There's a second box with some code that I then pasted below that because I wasn't sure what to do with it.
Obviously I'm an amateur and doing something wrong :smileyconfused: because I'm not getting the accordion. Any help is greatly appreciated.
I would also like to know how this works...as I was trying out some of the stuff from the StyleGuide on Friday, too. Some things worked "right out of the box"...some things did not. 😞
There's a second box with some code that I then pasted below that because I wasn't sure what to do with it. I am NO expert or even a novice on this, but my husband is pretty sure it goes in the global javascript file at the account or sub-account if enabled level. I'm sure someone else can provide a LOT more information/direction on this, but thought I'd at least pass the little I did know along.
I worked with one of our web guys to add that line to the global JS file on Friday, and no luck. 😞
@kona ' husband is correct. That second box of code is JavaScript that has to run in order to turn the html content into an accordion. The reason that it didn't work for @Chris_Hofer is due to the way in which Canvas loads page content. In essence, the reason that just pasting that code into the global JS file won't work is a matter of timing. The code in the global JS file loads and is run before the user content is injected by Canvas. The timing issue makes that simple one line of code to create an accordion a lot more difficult. I'm not quite sure why they approached it this way but the change happened around the time of draft state. When I was writing the code to create accordions and tabbed panels for USU's Custom/Design tools, I ended up writing a series of functions that makes sure the content has loaded and then triggers the JavaScript that I want applied.
I have pulled out and adapted some of my code that should work for creating an accordion.
Here is what your html would look like:
<div class="accordion" id="custom_accordion">
<h3>Panel 1</h3>
<div>
<p>Panel 1 contents.</p>
</div>
<h3>Panel 2</h3>
<div>
<p>Panel 2 contents.</p>
</div>
</div>
<div class="accordion ui-accordion--mini" id="custom_accordion">
<h3>Panel 1</h3>
<div>
<p>Panel 1 contents.</p>
</div>
<h3>Panel 2</h3>
<div>
<p>Panel 2 contents.</p>
</div>
</div>
Here is what would go in your global JavaScript file:
// If any of these elements exist, we will watch for page content in them to load
var pageContentWrappersArray = [
'#course_home_content', // Course Front Page
'#wiki_page_show', // Content page
'#discussion_topic', // Discussions page
'#course_syllabus', // Syllabus page
'#assignment_show', // Assignments page
'#wiki_page_revisions'
];
// Commands to run after the page content has loaded
function afterPageContentLoaded() {
'use strict';
console.log('Running code');
// Place the code you want to run here
// CUSTOM ACCORDION //
if ($('#custom_accordion').length > 0) {
// Wrap h3 elements with a link after the fact so it isn't confusing to mobile app users
$("#custom_accordion h3").each(function () {
$(this).contents().wrap('<a href="#" />');
});
// Create the accordion
$("#custom_accordion").accordion({header: 'h3'});
}
}
// Function that will check to see if the page content has loaded yet
function pageContentCheck(pageContentWrapperElement) {
'use strict';
var contentLoaded = false;
// Content Pages
if ($('.show-content').length > 0 && $('.show-content').children().length > 0) {
contentLoaded = true;
// Discussions
} else if ($('#discussion_topic').length > 0 && $('.user_content').text().length > 0) {
contentLoaded = true;
// Assignment (Teacher View)
} else if ($('#assignment_show .teacher-version').length > 0) {
contentLoaded = true;
} else if ($('#assignment_show .student-version').length > 0) {
contentLoaded = true;
} else if ($('#course_syllabus').length > 0) {
contentLoaded = true;
}
if (contentLoaded) {
console.log('Content has loaded');
afterPageContentLoaded();
} else {
setTimeout(function () {
console.log('Still no content, check again (' + pageContentWrapperElement + ')');
pageContentCheck(pageContentWrapperElement);
}, 100);
}
}
// Run the functions
$(document).ready(function () {
'use strict';
// Get Current UserID
var task,
i;
// Identify which page we are on and when the content has loaded
for (i = 0; i <= pageContentWrappersArray.length; i++) {
if ($(pageContentWrappersArray[i]).length > 0) {
// console.log(pageContentWrappersArray[i] + ' Found');
pageContentCheck(pageContentWrappersArray[i]);
break;
}
}
});
You will probably need to add some CSS to your stylesheet to counteract the default h3 margins as well as add some padding to the panel content area.
If anyone else has figured out other ways around the content load timing, I would love to hear about it.
Thanks so much for the help and taking the time to share the code!
Janetta
Mine is not nearly as thorough as yours but accordions appear to work in our test environment. One thing I've noticed is that the accordions seem not to work if you navigate to another page and press the back button to return to the page with the accordions. Refreshing the page will then bring the accordions back. We haven't tried anything in our production environment yet because I'm still playing around with it. I added only this to our javascript to get it to work:
/*
Activate Accordions
*/
$(document).ready(function(){
$('div.accordion-custom').accordion({heightStyle: "content"});
});
If you place any content below the accordion, it would create a blank space that was as big as the largest piece of accordion content so I had to add that heightStyle line in order to prevent that from happening.
Then I've always found it incredibly obnoxious to click on an accordion and have it expand into the middle of that accordion's content if it's a large amount of content. So I added this code to automatically scroll to the Accordion's header after the accordion expands:
/*
Scroll to top of accordion
*/
$( "#accordion-custom" ).accordion({
heightStyle: "content",
collapsible: true,
active: false,
activate: function( event, ui ) {
if(!$.isEmptyObject(ui.newHeader.offset())) {
$('html:not(:animated), body:not(:animated)').animate({ scrollTop: ui.newHeader.offset().top }, 'slow');
}
}
});
Then I was just playing with styling the accordions so they are little more eye-catching for our Elementary students. The resulting accordions looks like this:
I like the look that you have provided with your content. Can you provide more detail on how that was implemented - I don't intend to go out and try it, I am just trying to learn the way all of this is being done. Any clarification would be a big help.
I created this page that has a link to a jsfiddle that contains all the relevant code. Hope that helps!
Matthew:
I have added accordion tabs to several classrooms, without modification of the global script, and they work just fine - even when navigating away from the page.
This is the code I use, however when I went to the HTML Editor in this blog, the code did not produce the tabs!
<div class="enhanceable_content accordion">
<h3><a href="#">TYPE TITLE TO FIRST ACCORDION TAB</a></h3>
<div>
<p>TYPE CONTENT FOR FIRST ACCORDION TAB</p>
</div>
<h3><a href="#">TYPE TITLE TO SECOND ACCORDION TAB</a></h3>
<div>
<p>TYPE CONTENT FOR SECOND ACCORDION TAB</p>
</div>
<h3><a href="#">TYPE TITLE FOR THIRD ACCORDION TAB</a></h3>
<div>
<p>TYPE CONTENT FOR THIRD ACCORDION TAB</p>
</div>
</div>
Yeah, I noticed that nice little bit of code in that post by @jperkins . I'll update my post later for future readers.
Actually, I think I'm going to leave it as is for people who have access to edit global css and javascript. The version I posted above has the ability to fit each accordion to it's own content size and also has that "scroll to top" feature.
Hi Matt,
When I type that code in it looks great until I add content to one accordion and not the other because they all become the size of the largest one. How did you get them to be the size of their content only and have the scroll to top feature?
Thank you so much,
Karen Matson
@MattHanes , would your code snippet work if trying to embed video within the accordion, given that it starts off in a minimized state then enlarges when being played?
Yep, it works with YouTube embed code. You can see it in the Other Resources accordion tab here: Accordion Demo
I ended up writing a series of functions that makes sure the content has loaded and then triggers the JavaScript that I want applied.
Hi Kenneth and anybody else who may be interested,
For reasons too tedious for me to discuss here, I ended up testing your above approach against JavaScript's native load event. It turns out that a simple
window.addEventListener("load", function(event) {
... your code here ...
});
works more effectively and efficiently.
If you watch the network tab in your developer tools with a couple of console.log() statements, you will see that your approach fires prematurely before Canvas finishes loading all of its assets, whereas the load event waits until things are fully loaded.
Due to the asynchronous nature of all of this JavaScript loading into the DOM, your approach actually fires in a different sequence every time the page is refreshed. This can give rise to some erratic/unpredictable behavior in which sometimes scripts will work as expected and other times they won't (because they execute too early).
In contrast, the load event fires in a predictable manner every time - at the end. It also reduces page load time due to eliminating all of the control flow your approach requires and it is not as brittle since it doesn't rely on Canvas's element id's which Canvas developers could randomly change on you someday after an update.
It should also be noted on record that jQuery's $(document).ready() is not a good choice in this case for similar reasons - it doesn't fire predictably. It's analogous to forcing your users to roll a set of dice every time they try to view your content.
Best
@jnickerson1 , that does look beautifully simple. I am excited to give it a try! I had initially used the $(document).ready() approach and had experienced the unpredictability of it. A toss of the dice is a great analogy to what the experience was. Thank you immensely for sharing what you found. I know what I am going to do at work today :smileygrin:
Wow, thanks, @jnickerson1 , this is eye-opening!
Over lunch I just looked around for more on this and found this demo: $(document).ready VS window.addEventListener('load') - JSFiddle
The Canvas Styleguide is actually for the design of Canvas itself and not for content created inside Canvas. Some things in the styleguide will work in the rich-content editor but much (perhaps most?) of it will not. Proceed at your own risk.
That being said, I really love that there are faculty and instructional designers trying new and interesting things in content design. Giant boring walls of text are so over.
We like to use cool styling like it's 2015 (or later).
I would also be interested in knowing how you got the styling to work. Another problem with the accordion I have found is that they all accordions in a set open to the same size regardless of the size of the content they hold. Have you worked around that?
If you take a look at my code snippet above where I initialize the accordions in the javascript, you will see on line 5 that I set the heightstyle to "content" which makes each accordion the size of the content contained in that accordion.
Just for the record, I had almost zero javascript experience before we got Canvas a couple of months ago and I have literally pieced this entire thing together based on google searches. Use at your own risk!
I'll try to put together a public Canvas page that I can use to go into further detail on how I got things to look the way they do. It'll help everyone see it in action as well.
The page I said I would make: https://mcsd.instructure.com/courses/15534/
Janetta & Matthew
Some of the content in the style Guide will only work on a content page if the Global CSS file is updated with the code snippet in the second box, and then only if that snippet is sequenced in the right location in the global files, and often with more code used to make it load in the correct order.
Matthew: you seem to know the global script well enough to play in there.
Janetta: Several of us have been sharing some HTML content hacks in this group that will work without updating the global script. Check key-word "Code-Snippets" to find these. Also, Scott Dennis has created a public classroom where some of us will be providing much more of these types of enhancements - Coming soon!
Kelley
Kelley,
Code snippets are in my comfort zone. I get a kick out making those HTML content hacks. I look forward to checking out the course from Scott Dennis!
Thank you,
Janetta
I hope you like it!
It's brother (that I uploaded from) is being built to train adventurous faculty who also are not coders (also, as in neither am I), so the structure of the lesson pages might seem a bit pedestrian for those of you who code.
Now that its up for all those fancy Instructional Designer Group members, I suspect I'll start seeing that tone change a bit - but I hopenot too much, I still have so much to learn.
I am getting ready to start playing in our Global Script, but only on our test instance so I don't muck things up too badly - I tend to be much braver than I am smart:-}
Since the test environment gets overwritten every three weeks (and I'm too lazy to check the calendar to see when the next refresh is), I just created a separate sub-account in our production environment for testing these changes. Each sub-account can have it's own CSS and JS files if that feature is enabled at the higher level account.
This is such a great line of questions and dialogue!
What I was looking for was something similar to the way bootstrap has been implemented in places like Wordpress environments. These things should just be whitelisted globally!
See this example: http://getbootstrap.com/css/#buttons
When I was previously at UConn, they had their own WP instance called aurora where all of these features were baked in as a plugin(s) and themes. Home | Aurora
Maybe this would help?
Here's some code you can use on the page itself (without doing anything to the global javascript) with the HTML editor. Note: There is an issue with the sizing of accordion tabs using this code. The sizing of each content tab will default to the largest content tab. If anyone has a fix to this I would love to see it! See picture below code.
Code:
<div class="enhanceable_content accordion">
<h3><a href="#">TYPE TITLE TO FIRST ACCORDION TAB</a></h3>
<div>
<p>TYPE CONTENT FOR FIRST ACCORDION TAB</p>
</div>
<h3><a href="#">TYPE TITLE TO SECOND ACCORDION TAB</a></h3>
<div>
<p>TYPE CONTENT FOR SECOND ACCORDION TAB</p>
</div>
<h3><a href="#">TYPE TITLE FOR THIRD ACCORDION TAB</a></h3>
<div>
<p>TYPE CONTENT FOR THIRD ACCORDION TAB</p>
</div>
</div>
Sizing Example:
awebster, if you haven't already could you add the code for this into the Canvas Hacks classroom?
Yes, I will add it. I'm just still playing catch-up on everything else from InstructCon
@kona & Amanda - It is already in there. I think I put it in my original course before I copied it to the CanvasHacks classroom.
Hi
Do you have a way to to close/ hide the accordion for the first one initially?
Mine just open the first item right away
I used the code I have posted here at this jfiddle in order to start with the first accordion closed: JS and CSS for Canvas - JSFiddle
You can see what it looks like on this page: Modifying CSS and Javascript
Janetta:
This is the code that I use, and have included in the CanvasHacks Demo Course:
<div class="enhanceable_content accordion">
<h3><a href="#">TYPE TITLE TO FIRST ACCORDION TAB</a></h3>
<div>
<p>TYPE CONTENT FOR FIRST ACCORDION TAB</p>
</div>
<h3><a href="#">TYPE TITLE TO SECOND ACCORDION TAB</a></h3>
<div>
<p>TYPE CONTENT FOR SECOND ACCORDION TAB</p>
</div>
<h3><a href="#">TYPE TITLE FOR THIRD ACCORDION TAB</a></h3>
<div>
<p>TYPE CONTENT FOR THIRD ACCORDION TAB</p>
</div>
</div>
It produces the following results:
There is an issue with the sizing of accordion tabs using this code. The sizing of each content tab will default to the largest content tab, but it does work in a Canvas page. And yes, you can embed videos, images even complex text formatting on each tab.
I hope this helps,
KLM
Thank you, Kelley!
Janetta
You are very welcome!
I am not a coder, and I don't play one on TV, but I do teach non-coding faculty how to enhance their Canvas classrooms with bits of HTML.
Hi,
So without modifying Javascripts, there is no way to resize or default close that first Row right?
Thanks
As far as I know, the answer is "No". Some of the really smart folks in the Instructional Designers group may be able to answer that question. As I said, I sure ain't one of them there geeky coders, although I often wish I were and am getting better every day:smileysilly:
We were able to add a line of html so the accordion containers are a bit larger and also display add a vertical scroll bar.
The line goes below:
<h3><a href="#">TYPE TITLE TO FIRST ACCORDION TAB</a></h3>
Add this:
<div style="max-height: 30%;">
Play around with the max-height % for a larger container, and if the content doesn't fit, you get a scroll bar so all content is visible. Haven't found a way to have it adjust to the amount of content in each accordion section.
We don't go into the javascript.
Hope this helps.
To participate in the Instructure Community, you need to sign up or log in:
Sign In
This discussion post is outdated and has been archived. Please use the Community question forums and official documentation for the most current and accurate information.