Skip to content

Instantly share code, notes, and snippets.

@peponi
Last active May 6, 2019 12:41
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 peponi/8fc691a26cc83abfe5c24027f20cb98c to your computer and use it in GitHub Desktop.
Save peponi/8fc691a26cc83abfe5c24027f20cb98c to your computer and use it in GitHub Desktop.
details element polyfill for IE11, supoorts elements inside summary
/**
* based on
* @url https://github.com/rstacruz/details-polyfill
* @todo https://www.sitepoint.com/fixing-the-details-element/
* @todo https://www.smashingmagazine.com/2014/11/complete-polyfill-html5-details-element/
*/
const detailsPolyfillEs6 = ({
CSS_CLASS = 'no-details',
CSS_STRING = false,
APPEND_CSS = true,
DEBUG = false
} = {}) => {
const DETAILS = 'details';
const SUMMARY = 'summary';
/*
* Checks for support for `<details>`
*/
const checkSupport = () => {
const el = document.createElement(DETAILS);
if (!('open' in el)) return false;
el.innerHTML = '<' + SUMMARY + '>a</' + SUMMARY + '>b';
document.body.appendChild(el);
const diff = el.offsetHeight;
el.open = true;
const result = (diff !== el.offsetHeight);
document.body.removeChild(el);
return result;
};
// check if passed element is a <summary> else take parent element and check again
const getSummary = (el) => {
// I saw on IE11 that e.target can be null in some case
if (el === null) return false;
return el.nodeName.toLowerCase() !== SUMMARY ? getSummary(el.parentNode) : el;
};
/*
* Click handler for `<summary>` tags
*/
const clickHandler = (e) => {
// INFO: this is maybe performance relevant for you
// because I use a recursive function,
// the clickHandler will loop up the tree ON EVERY CLICK IN THE INTERNET EXPLORER,
// until a <summary> or the end of the node tree has been found
const summaryEl = getSummary(e.target);
if (summaryEl && summaryEl.nodeName && summaryEl.nodeName.toLowerCase() === SUMMARY) {
const detailsEl = summaryEl.parentNode;
// if parent element of <summary> is a <details> toggle the state
if (detailsEl && detailsEl.nodeName && detailsEl.nodeName.toLowerCase() === DETAILS) {
// toggle the visual state
if (detailsEl.getAttribute('open')) {
detailsEl.open = false;
detailsEl.removeAttribute('open');
} else {
detailsEl.open = true;
detailsEl.setAttribute('open', 'open');
}
}
}
};
/*
* Injects styles (idempotent)
*/
const injectStyle = (id, style) => {
if (document.getElementById(id)) return;
const el = document.createElement('style');
el.id = id;
el.innerHTML = style;
document.getElementsByTagName('head')[0].appendChild(el);
};
/**
* INIT
*/
const detailsIsSupported = checkSupport();
DEBUG && console.log('detailsIsSupported = ', detailsIsSupported);
// if details element is support in the current browser, do nothing
if (detailsIsSupported) return;
// just add event listener & CSS for IE
window.addEventListener('click', clickHandler);
// if customDetailsPolyfill has been initialized with APPEND_CSS = false
// do not write the styles for the <summary> marker in the <head>
//
// usefull if you don't need the marker by default
// you can hide the marker with CSS for chrome & firefox
//
// summary::-webkit-details-marker { display: none; }
// summary::-moz-list-bullet { list-style-type: none; }
//
if (APPEND_CSS === false) return;
document.documentElement.className += ` ${CSS_CLASS}`;
const cssString = CSS_STRING || `
.${CSS_CLASS} ${DETAILS} * {
display: none;
}
.${CSS_CLASS} ${DETAILS} ${SUMMARY},
.${CSS_CLASS} ${DETAILS} ${SUMMARY} * {
display: block;
}
.${CSS_CLASS} ${DETAILS}[open] * {
display: block;
}`;
DEBUG && console.log(cssString);
injectStyle('details-polyfill-es6-style has been injected following styles to HEAD', cssString);
};
export default detailsPolyfillEs6;
import detailsPolyfillEs6 from './polyfill/details-polyfill-es6';
// show console logs in IE11
detailsPolyfillEs6({DEBUG: true});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment