JSFiddle - React, Tailwind, and code Playground
Collapsible
by tonytlwu
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.10/handlebars.min.js"></script>
<script type="text/html" id="template-collapsible">
<div class="panel panel-default" data-collapse-id="{{id}}">
<h4 class="panel-title collapsed" target="#collapse-{{id}}" data-toggle="collapse">{{title}}</h4>
<div class="panel-collapse collapse" id="collapse-{{id}}">
<div class="panel-body"></div>
</div>
</div>
</script>
<p class="item-1">Paragraph 1</p>
<p class="item-2">Paragraph 2</p>
<div data-fl-widget-instance><div data-collapsible-start-id="34">Paragraphs 3 - 4</div></div>
<p class="item-3">Paragraph 3</p>
<p class="item-4">Paragraph 4</p>
<div data-fl-widget-instance><div data-collapsible-start-id="56">Paragraphs 5 - 6</div></div>
<p class="item-5">Paragraph 5</p>
<div class="widget-5-1" data-fl-widget-instance></div>
<p class="item-5-2">Paragraph 5.2</p>
<div class="widget-5-3" data-fl-widget-instance></div>
<p class="item-6">Paragraph 6</p>
<div data-fl-widget-instance><div data-collapsible-end-id></div></div>
<p class="item-7">Paragraph 7</p>
<p class="item-8">Paragraph 8</p>
<div data-fl-widget-instance><div data-collapsible-start-id="910">Paragraphs 9 - 10</div></div>
<p class="item-9">Paragraph 9</p>
<p class="item-10">Paragraph 10</p>
CSS
[data-collapsible-start-id] {
font-weight: bold;
padding-bottom: 4px;
border-bottom: 1px solid green;
}
[data-collapsible-end-id] {
border-bottom: 1px solid red;
}
.panel {
border: 1px solid #ddd;
border-radius: 4px;
margin-bottom: 20px;
padding: 15px;
}
JavaScript
+ function($) {
'use strict';
// COLLAPSIBLE CLASS DEFINITION
// ======================
var Collapsible = function(el) {
// Plugin initialization
}
Collapsible.SELECTORS = {
start: '[data-collapsible-start-id]',
end: '[data-collapsible-end-id]',
widget: '[data-fl-widget-instance]'
}
Collapsible.prototype.widgetIsCollapsibleStart = function ($widget){
return $widget.find(Collapsible.SELECTORS.start).length > 0;
}
Collapsible.prototype.widgetIsCollapsibleEnd = function ($widget){
return $widget.find(Collapsible.SELECTORS.end).length > 0;
}
Collapsible.prototype.widgetIsCollapsible = function ($widget){
return $widget.find(Collapsible.SELECTORS.start).length > 0
|| $widget.find(Collapsible.SELECTORS.end).length > 0;
}
// COLLAPSIBLE INITIALIZATION
// =====================
$.fn.collapsify = function (){
return this.each(function () {
// Find the widget container for Collapsible Start
var $collapsibleStart = $(this);
var id = $collapsibleStart.data('collapsible-start-id').toString();
var $startWidget = $collapsibleStart.closest(Collapsible.SELECTORS.widget);
var title = $collapsibleStart.html();
// Find all subsequent content nodes
var $content = $startWidget.nextUntil(Collapsible.SELECTORS.widget);
var $next;
if ($content.length) {
$next = $content.last().next();
} else {
$next = $startWidget.next();
}
while ($next.length && !Collapsible.prototype.widgetIsCollapsible($next)) {
$content = $content.add($next);
$content = $content.add($next.nextUntil(Collapsible.SELECTORS.widget));
$next = $content.last().next();
}
if (Collapsible.prototype.widgetIsCollapsibleEnd($next)) {
$next.remove();
}
//
var collapsibleTemplate = Handlebars.compile($('#template-collapsible').html());
var data = {
id: id,
title: title
...