Skip to content

Instantly share code, notes, and snippets.

@stewartknapman
Created June 11, 2019 18:48
Show Gist options
  • Save stewartknapman/ff9f52b97fab157285b2aa94903a7e9b to your computer and use it in GitHub Desktop.
Save stewartknapman/ff9f52b97fab157285b2aa94903a7e9b to your computer and use it in GitHub Desktop.
(function () {
if (!document.querySelector && !window.addEventListener && !("classList" in document.createElement("p"))) return;
var ready = function (callback, ctx) {
if (typeof callback !== 'function') return;
if (document.readyState !== "loading") {
callback.apply(ctx);
} else {
document.addEventListener("DOMContentLoaded", function () {
callback.apply(ctx);
});
}
};
var each = function (arr, callback, ctx) {
var r;
for (var i = 0; i < arr.length; i++) {
ctx = ctx || arr[i];
r = callback.apply(ctx, [arr[i], i]);
if (r == false) break;
}
};
var debounce = function (callback, wait, ctx) {
var timeout, timestamp, args;
wait = wait || 100;
var later = function() {
var last = new Date().getTime() - timestamp;
if (last < wait && last >= 0) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null;
callback.apply(ctx, args);
}
};
return function () {
ctx = ctx || this;
args = arguments;
timestamp = new Date().getTime();
if (!timeout) timeout = setTimeout(later, wait);
};
};
/* Accordian Main */
var Accordian = function (ele, selectors) {
this.classes = {
open: 'accordion__section--open'
};
this.selectors = selectors;
this.ele = ele;
this.sections = this._getSections();
this._setContentHeights();
this._addEventListeners();
};
Accordian.prototype.toggleSection = function (target) {
var targetEle = this.ele.querySelector(target);
var currentSection = targetEle.closest(this.selectors.sections);
var isclosed = true;
if (currentSection.classList.contains(this.classes.open)) {
isclosed = false;
}
this.closeSections();
if (isclosed) {
var content = currentSection.querySelector(this.selectors.content);
currentSection.classList.add(this.classes.open);
content.style.height = content.getAttribute('data-height');
}
};
Accordian.prototype.closeSections = function () {
each(this.sections, function (section) {
var content = section.querySelector(this.selectors.content);
content.style.height = '0';
section.classList.remove(this.classes.open);
}, this);
};
Accordian.prototype._addEventListeners = function () {
var _this = this;
this.actions = this.ele.querySelectorAll(this.selectors.actions);
each(this.actions, function (action) {
action.addEventListener('click', function (e) {
var target = e.currentTarget.getAttribute('href');
e.preventDefault();
_this.toggleSection(target);
});
});
window.addEventListener('resize', debounce(function () {
_this._setContentHeights();
}));
};
Accordian.prototype._getSections = function () {
var sectionClassName = this.selectors.sections.replace('.','');
if (this.ele.classList.contains(sectionClassName)) {
return [this.ele];
} else {
return this.ele.querySelectorAll(this.selectors.sections);
}
};
Accordian.prototype._setContentHeights = function () {
var contents = this.ele.querySelectorAll(this.selectors.content);
each(contents, function (content) {
var transition = window.getComputedStyle(content).transition;
var currentHeightStyle = window.getComputedStyle(content).height;
content.style.transition = 'none';
content.style.height = 'auto';
content.setAttribute('data-height', content.offsetHeight+'px');
content.style.height = currentHeightStyle;
content.style.transition = transition;
});
};
// Plural
var Accordians = function () {
this.selectors = {
ele: '[data-accordion]',
sections: '.accordion__section',
content: '.accordion__content',
actions: 'a'
}
this.init();
};
Accordians.prototype.init = function () {
this.eles = document.querySelectorAll(this.selectors.ele);
if (!this.eles.length) return;
each(this.eles, function (ele) {
new Accordian(ele, this.selectors);
}, this);
};
// Run everything
ready(function () {
new Accordians();
});
})();
<div class="accordion" data-accordion>
<!-- Start section -->
<div class="accordion__section accordion__section--features accordion__section--open">
<div class="accordion__header">
<h3>
<a href="#section1">
Section 1 title
{% include 'icon-plus' %}
{% include 'icon-minus' %}
</a>
</h3>
</div>
<div class="accordion__content" id="section1">
<ul class="rte">
Section 1 content
</ul>
</div>
</div>
<!-- End section -->
</div>
.accordion {
margin-bottom: $grid-gutter;
border-bottom: $color-border solid 1px;
ul {
padding-left: 1.25em;
}
}
.accordion__header {
padding-top: 1.5em;
border-top: $color-border solid 1px;
a {
display: block;
}
.icon {
float: right;
.no-js & {
display: none !important;
}
}
.icon-plus {
display: block;
.accordion__section--open & {
display: none;
}
}
.icon-minus {
display: none;
.accordion__section--open & {
display: block;
}
}
}
.accordion__content {
overflow: hidden;
.js & {
height: 0;
transition: .2s height ease-in-out;
}
.no-js &,
.accordion__section--open & {
height: auto;
margin-bottom: 1.5em;
}
}
@jjp2133
Copy link

jjp2133 commented Aug 7, 2019

Hi @stewartknapman, thank you so much for the revised accordion code. I'm still struggling a bit, as I am new to coding.

I created and linked the snippet by replacing {{product.description}} with my own {%include'myaccordionfilename'%}, and even used split heading titles from your original codes since I wanted it integrated into the heading h6. However, this time, all the heading accordions open and don't close, all while showing the content of the accordion sections.

Do you mind guiding me what I have done incorrectly? Perhaps I did not put the JS and SCSS files in the correct assets and/or snippets...

Thank you in advance!!

@stewartknapman
Copy link
Author

@jjp2133 It’s hard for me to tell exactly what’s going on without seeing the code. Can you post the contents of your snippet so I can have a look?

@blueseanj
Copy link

Hi I tried to use this version of the accordion and the previous one on my shopify but couldnt work. it shows liquid error on my product page. Im using Brooklyn theme, any help on the path of where to place those files snippets/assets/templates/ etc ? That would be really helpful! Thanks.

@googula
Copy link

googula commented Nov 19, 2019

Can this change accordion change to all close and only open when its click?
like your previous accordion

@jschuler00
Copy link

Where are the icon include files?

@stewartknapman
Copy link
Author

This was based on the Debut theme which has icons in the snippets folder. You can aways replace the icon includes with your own icons or svg

@edwardboyce
Copy link

I have the opposite problem in that all the tabs are open when loaded, then once tab is clicked they resume correct behaviour. I'm really struggling to see why it's doing this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment