Skip to content

Instantly share code, notes, and snippets.

@markfullmer
Last active October 6, 2021 18:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save markfullmer/68d7d84090501c29b948b924040de3da to your computer and use it in GitHub Desktop.
Save markfullmer/68d7d84090501c29b948b924040de3da to your computer and use it in GitHub Desktop.
Convert Zurb Foundation Accordion to generic details/summary using DomDocument
<?php
$input = 'Some text<a href="#">Test</a><ul class="accordion" data-accordion role="tablist">
<li class="accordion-navigation" role="presentation">
<a href="#panel1d" role="tab" id="panel1d-heading" aria-controls="panel1d">Accordion 1</a>
<div id="panel1d" class="content active" role="tabpanel" aria-labelledby="panel1d-heading">
Panel 1. Lorem ipsum dolor
</div>
</li>
<li class="accordion-navigation" role="presentation">
<a href="#panel2d" role="tab" id="panel2d-heading" aria-controls="panel2d">Accordion 2</a>
<div id="panel2d" class="content" role="tabpanel" aria-labelledby="panel2d-heading">
Panel 2. Lorem ipsum dolor<a href="#">foo</a>
</div>
</li>
<li class="accordion-navigation" role="presentation">
<a href="#panel3d" role="tab" id="panel3d-heading" aria-controls="panel3d">Accordion 3</a>
<div id="panel3d" class="content" role="tabpanel" aria-labelledby="panel3d-heading">
Panel 3. Lorem ipsum dolor
</div>
</li>
</ul>';
$input2 = 'Some text<a href="#">Test</a><ul class="accordion" data-accordion="">
<li class="accordion-navigation"><a href="#citations" aria-expanded="false">Citations</a><div>
<pre class="content" id="citations"><sup>1 Texas Department of Family and Protective Services. Family First Prevention Act. Retrieved from https://www.dfps.state.tx.us/Child_Protection/Family_First/default.asp
2 Chen, E., Brody, G. H., &amp; Miller, G. E. (2017). Childhood close family relationships and health. The American psychologist, 72(6), 555–566. Retrieved from https://doi.org/10.1037/amp0000067
</pre></div></li>
<li class="accordion-navigation"><a href="#pdf" aria-expanded="false">PDF Version</a><br>
<div class="content" id="pdf">test<a href="/sites/default/files/CFRPBrief_B0440121_SupportingPregnantandParentingTeensinCare.pdf" target="_blank">Supporting Pregnant and Parenting Teens in Care with Home Visiting (PDF)</a></div>
</li>
</ul>';
function appendHTML(DOMNode $parent, $source) {
$tmpDoc = new DOMDocument();
$tmpDoc->loadHTML($source);
foreach ($tmpDoc->getElementsByTagName('body')->item(0)->childNodes as $node) {
$node = $parent->ownerDocument->importNode($node, true);
$parent->appendChild($node);
}
}
function DOMinnerHTML(DOMNode $element) {
$innerHTML = "";
$children = $element->childNodes;
foreach ($children as $child) {
$innerHTML .= $element->ownerDocument->saveHTML($child);
}
return $innerHTML;
}
function convertFoundationAccordion($text) {
$original = $text;
// LibXML requires that the html is wrapped in a root node.
$text = '<root>' . $text . '</root>';
$dom = new \DOMDocument();
$dom->preserveWhiteSpace = FALSE;
libxml_use_internal_errors(TRUE);
$dom->loadHTML(mb_convert_encoding($text, 'HTML-ENTITIES', 'UTF-8'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$uls = $dom->getElementsByTagName('ul');
if ($uls->length === 0) {
return $original;
}
foreach ($uls as $ul) {
$classes = $ul->getAttribute('class');
if (strpos($classes, 'accordion') === FALSE) {
continue;
}
$lis = $ul->getElementsByTagName('li');
if ($lis->length === 0) {
continue;
}
$convert = TRUE;
$content = '';
$titleObjects = [];
$bodyObjects = [];
foreach ($lis as $key => $li) {
if (!$convert) {
continue;
}
$classes = $li->getAttribute('class');
if (strpos($classes, 'accordion-navigation') === FALSE) {
continue;
}
$titleObjects[$key] = $li->getElementsByTagName('a');
$bodyObjects[$key] = $li->getElementsByTagName('div');
if ($bodyObjects[$key][0] && $titleObjects[$key][0]) {
if (isset($bodyObjects[$key][0]->nodeValue) && isset($titleObjects[$key][0]->nodeValue)) {
$content .= '<details><summary>' . $titleObjects[$key][0]->nodeValue . '</summary>' . DOMInnerHTML($bodyObjects[$key][0]) . '</details>';
}
else {
$convert = FALSE;
}
}
else {
$convert = FALSE;
}
}
if ($convert) {
$elem = $dom->createElement('div');
appendHTML($elem, $content);
$ul->parentNode->replaceChild($elem, $ul);
}
}
// Get innerHTML of root node.
$html = "";
foreach ($dom->getElementsByTagName('root')->item(0)->childNodes as $child) {
// Re-serialize the HTML.
$html .= $dom->saveHTML($child);
}
return $html;
}
$output = convertFoundationAccordion($input);
print_r($output);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment