Skip to content

Instantly share code, notes, and snippets.

@calebergh
Last active March 10, 2020 18:33
Show Gist options
  • Save calebergh/7077e215a6d4818acce9b8b170565e77 to your computer and use it in GitHub Desktop.
Save calebergh/7077e215a6d4818acce9b8b170565e77 to your computer and use it in GitHub Desktop.
Modernized polyfill to support proper behavior for summary / details HTML elements in Edge (legacy)
void(function(root, factory) {
if (typeof define === 'function' && define.amd) define(factory)
else if (typeof exports === 'object') module.exports = factory()
else factory()
}(this, function() {
var el = document.createElement('details');
if (!('open' in el)) enableSupport();
// include contents with size, otherwise diff sometimes returns 0
el.innerHTML = '<summary><p>a</p></summary><p></p>';
// put it off the page so there's no flash of content
el.style.position = 'absolute';
el.style.left = '-999em';
document.body.appendChild(el);
var diff = el.offsetHeight;
el.open = true;
setTimeout(function() {
var result = (diff !== el.offsetHeight);
document.body.removeChild(el);
if ( ! result) enableSupport();
}, 500);
/*
* Click handler for `<summary>` tags
*/
function clickHandler(e) {
// use closest to capture clicks on elements within the summary as well
if (e.target.nodeName.toLowerCase() === 'summary' || e.target.closest('summary')) {
// use closest to handle click targets nested within summary
var details = e.target.closest('details');
if (!details) return;
if (details.getAttribute('open')) {
details.open = false;
details.removeAttribute('open');
} else {
details.open = true;
details.setAttribute('open', 'open');
}
}
}
function enableSupport() {
// Add a classname
document.documentElement.className += ' no-details';
window.addEventListener('click', clickHandler);
}
}));
/**
* Required SCSS to make polyfill work properly:
*
* html.no-details {
* details:not([open]) > :not(summary) {
* display: none;
* }
* }
*/
@calebergh
Copy link
Author

calebergh commented Feb 26, 2020

This polyfill is largely based on this: https://github.com/rstacruz/details-polyfill

However, in my use case, the summary element contained children elements, and the click target was not properly identifying it as being within a summary, so this updated code does a few things differently:

  1. Responds to clicks for summary and children of summary using the modern .closest() JS method .
  2. Pulls the styles out of javascript and into external SCSS / CSS files (and removes some undesired styles that were adding the carat indicator).
  3. Other optimizations to remove static strings (which don't minify / compress as well).

Minified, this script comes in at a lightweight 709 bytes uncompressed, and 391 bytes gzipped

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