Details
About
What does it do?
- Allows users to reveal more detailed information if they need it.
- Allows users to scan the page more easily.
When to use it?
- When you need to provide more detailed information.
- When you need to hide extra information that only some users will need.
- When you only need to provide 1 piece of extra information on the given subject.
When not to use it?
- To hide information that is important to the majority of users
- If you need to provide more than 1 piece of extra information related to a given subject. In this instance, use an Accordion.
- To provide extra context inside a form. Users mistake it for a text link and worry they'll lose their data if they click.
How it works?
- The details component expands into more detailed text when a user clicks on it.
- Inside the
<details>
tag, include 1<summary>
and 1<div>
tag as direct children of<details>
- Place your link text inside
<summary>
and the important information inside the<div>
.
Using with IE11?
- Make sure you include the polyfill in the recommended JavaScript below as the
<details>
and<summary>
elements are not supported at IE11.
Closed
Detail heading
Lorem ipsum dolar sit...
HTML markup
<details class="wmnds-details">
<summary class="wmnds-link">
Detail heading
</summary>
<div class="wmnds-details__content">
<p>Lorem ipsum dolar sit...</p>
</div>
</details>
Nunjucks markup
{% from "wmnds/components/details/_details.njk" import wmndsDetails %}
{{
wmndsDetails({
headingText: "Detail heading",
headingHTML: null,
contentText: null,
contentHTML: "<p><strong>Some random subtitle</strong></p>
<p>Lorem ipsum dolor sit...</p>",
isOpen: false
})
}}
Nunjucks properties
Name | Type | Description |
---|---|---|
headingText | string | Required. Text content for heading line. If headingHTML is supplied, this is ignored. |
headingHTML | string | Required. HTML content for heading line. |
contentText | string | Required. The text content of each section, which is hidden when the section is closed. If contentHTML is supplied, this is ignored. |
contentHTML | string | Required. The HTML content of each section, which is hidden when the section is closed. |
isOpen | boolean | If true, details will be expanded upon initial load. Defaults to false . |
Recommended javascript (browser compatible)
"use strict";
/*
Details Element Polyfill 2.4.0
Copyright © 2019 Javan Makhmali
*/
/* eslint-disable */
(function() {
'use strict';
var element = document.createElement('details');
var elementIsNative = typeof HTMLDetailsElement != 'undefined' && element instanceof HTMLDetailsElement;
var support = {
open: 'open' in element || elementIsNative,
toggle: 'ontoggle' in element
};
var styles = '\ndetails, summary {\n display: block;\n}\ndetails:not([open]) > *:not(summary) {\n display: none;\n}\nsummary::before {\n content: "►";\n padding-right: 0.3rem;\n font-size: 0.6rem;\n cursor: default;\n}\n[open] > summary::before {\n content: "▼";\n}\n';
var _ref = [],
forEach = _ref.forEach,
slice = _ref.slice;
if (!support.open) {
polyfillStyles();
polyfillProperties();
polyfillToggle();
polyfillAccessibility();
}
if (support.open && !support.toggle) {
polyfillToggleEvent();
}
function polyfillStyles() {
document.head.insertAdjacentHTML('afterbegin', '<style>' + styles + '</style>');
}
function polyfillProperties() {
var prototype = document.createElement('details').constructor.prototype;
var setAttribute = prototype.setAttribute,
removeAttribute = prototype.removeAttribute;
var open = Object.getOwnPropertyDescriptor(prototype, 'open');
Object.defineProperties(prototype, {
open: {
get: function get() {
if (this.tagName == 'DETAILS') {
return this.hasAttribute('open');
} else {
if (open && open.get) {
return open.get.call(this);
}
}
},
set: function set(value) {
if (this.tagName == 'DETAILS') {
return value ? this.setAttribute('open', '') : this.removeAttribute('open');
} else {
if (open && open.set) {
return open.set.call(this, value);
}
}
}
},
setAttribute: {
value: function value(name, _value) {
var _this = this;
var call = function call() {
return setAttribute.call(_this, name, _value);
};
if (name == 'open' && this.tagName == 'DETAILS') {
var wasOpen = this.hasAttribute('open');
var result = call();
if (!wasOpen) {
var summary = this.querySelector('summary');
if (summary) summary.setAttribute('aria-expanded', true);
triggerToggle(this);
}
return result;
}
return call();
}
},
removeAttribute: {
value: function value(name) {
var _this2 = this;
var call = function call() {
return removeAttribute.call(_this2, name);
};
if (name == 'open' && this.tagName == 'DETAILS') {
var wasOpen = this.hasAttribute('open');
var result = call();
if (wasOpen) {
var summary = this.querySelector('summary');
if (summary) summary.setAttribute('aria-expanded', false);
triggerToggle(this);
}
return result;
}
return call();
}
}
});
}
function polyfillToggle() {
onTogglingTrigger(function(element) {
element.hasAttribute('open') ? element.removeAttribute('open') : element.setAttribute('open', '');
});
}
function polyfillToggleEvent() {
if (window.MutationObserver) {
new MutationObserver(function(mutations) {
forEach.call(mutations, function(mutation) {
var target = mutation.target,
attributeName = mutation.attributeName;
if (target.tagName == 'DETAILS' && attributeName == 'open') {
triggerToggle(target);
}
});
}).observe(document.documentElement, {
attributes: true,
subtree: true
});
} else {
onTogglingTrigger(function(element) {
var wasOpen = element.getAttribute('open');
setTimeout(function() {
var isOpen = element.getAttribute('open');
if (wasOpen != isOpen) {
triggerToggle(element);
}
}, 1);
});
}
}
function polyfillAccessibility() {
setAccessibilityAttributes(document);
if (window.MutationObserver) {
new MutationObserver(function(mutations) {
forEach.call(mutations, function(mutation) {
forEach.call(mutation.addedNodes, setAccessibilityAttributes);
});
}).observe(document.documentElement, {
subtree: true,
childList: true
});
} else {
document.addEventListener('DOMNodeInserted', function(event) {
setAccessibilityAttributes(event.target);
});
}
}
function setAccessibilityAttributes(root) {
findElementsWithTagName(root, 'SUMMARY').forEach(function(summary) {
var details = findClosestElementWithTagName(summary, 'DETAILS');
summary.setAttribute('aria-expanded', details.hasAttribute('open'));
if (!summary.hasAttribute('tabindex')) summary.setAttribute('tabindex', '0');
if (!summary.hasAttribute('role')) summary.setAttribute('role', 'button');
});
}
function eventIsSignificant(event) {
return !(event.defaultPrevented || event.ctrlKey || event.metaKey || event.shiftKey || event.target.isContentEditable);
}
function onTogglingTrigger(callback) {
addEventListener('click', function(event) {
if (eventIsSignificant(event)) {
if (event.which <= 1) {
var element = findClosestElementWithTagName(event.target, 'SUMMARY');
if (element && element.parentNode && element.parentNode.tagName == 'DETAILS') {
callback(element.parentNode);
}
}
}
}, false);
addEventListener('keydown', function(event) {
if (eventIsSignificant(event)) {
if (event.keyCode == 13 || event.keyCode == 32) {
var element = findClosestElementWithTagName(event.target, 'SUMMARY');
if (element && element.parentNode && element.parentNode.tagName == 'DETAILS') {
callback(element.parentNode);
event.preventDefault();
}
}
}
}, false);
}
function triggerToggle(element) {
var event = document.createEvent('Event');
event.initEvent('toggle', false, false);
element.dispatchEvent(event);
}
function findElementsWithTagName(root, tagName) {
return (root.tagName == tagName ? [root] : []).concat(typeof root.getElementsByTagName == 'function' ? slice.call(root.getElementsByTagName(tagName)) : []);
}
function findClosestElementWithTagName(element, tagName) {
if (typeof element.closest == 'function') {
return element.closest(tagName);
} else {
while (element) {
if (element.tagName == tagName) {
return element;
} else {
element = element.parentNode;
}
}
}
}
})();
Recommended javascript (ES6)
/*
Details Element Polyfill 2.4.0
Copyright © 2019 Javan Makhmali
*/
/* eslint-disable */
(function() {
'use strict';
var element = document.createElement('details');
var elementIsNative =
typeof HTMLDetailsElement != 'undefined' && element instanceof HTMLDetailsElement;
var support = {
open: 'open' in element || elementIsNative,
toggle: 'ontoggle' in element
};
var styles =
'\ndetails, summary {\n display: block;\n}\ndetails:not([open]) > *:not(summary) {\n display: none;\n}\nsummary::before {\n content: "►";\n padding-right: 0.3rem;\n font-size: 0.6rem;\n cursor: default;\n}\n[open] > summary::before {\n content: "▼";\n}\n';
var _ref = [],
forEach = _ref.forEach,
slice = _ref.slice;
if (!support.open) {
polyfillStyles();
polyfillProperties();
polyfillToggle();
polyfillAccessibility();
}
if (support.open && !support.toggle) {
polyfillToggleEvent();
}
function polyfillStyles() {
document.head.insertAdjacentHTML('afterbegin', '<style>' + styles + '</style>');
}
function polyfillProperties() {
var prototype = document.createElement('details').constructor.prototype;
var setAttribute = prototype.setAttribute,
removeAttribute = prototype.removeAttribute;
var open = Object.getOwnPropertyDescriptor(prototype, 'open');
Object.defineProperties(prototype, {
open: {
get: function get() {
if (this.tagName == 'DETAILS') {
return this.hasAttribute('open');
} else {
if (open && open.get) {
return open.get.call(this);
}
}
},
set: function set(value) {
if (this.tagName == 'DETAILS') {
return value ? this.setAttribute('open', '') : this.removeAttribute('open');
} else {
if (open && open.set) {
return open.set.call(this, value);
}
}
}
},
setAttribute: {
value: function value(name, _value) {
var _this = this;
var call = function call() {
return setAttribute.call(_this, name, _value);
};
if (name == 'open' && this.tagName == 'DETAILS') {
var wasOpen = this.hasAttribute('open');
var result = call();
if (!wasOpen) {
var summary = this.querySelector('summary');
if (summary) summary.setAttribute('aria-expanded', true);
triggerToggle(this);
}
return result;
}
return call();
}
},
removeAttribute: {
value: function value(name) {
var _this2 = this;
var call = function call() {
return removeAttribute.call(_this2, name);
};
if (name == 'open' && this.tagName == 'DETAILS') {
var wasOpen = this.hasAttribute('open');
var result = call();
if (wasOpen) {
var summary = this.querySelector('summary');
if (summary) summary.setAttribute('aria-expanded', false);
triggerToggle(this);
}
return result;
}
return call();
}
}
});
}
function polyfillToggle() {
onTogglingTrigger(function(element) {
element.hasAttribute('open') ?
element.removeAttribute('open') :
element.setAttribute('open', '');
});
}
function polyfillToggleEvent() {
if (window.MutationObserver) {
new MutationObserver(function(mutations) {
forEach.call(mutations, function(mutation) {
var target = mutation.target,
attributeName = mutation.attributeName;
if (target.tagName == 'DETAILS' && attributeName == 'open') {
triggerToggle(target);
}
});
}).observe(document.documentElement, {
attributes: true,
subtree: true
});
} else {
onTogglingTrigger(function(element) {
var wasOpen = element.getAttribute('open');
setTimeout(function() {
var isOpen = element.getAttribute('open');
if (wasOpen != isOpen) {
triggerToggle(element);
}
}, 1);
});
}
}
function polyfillAccessibility() {
setAccessibilityAttributes(document);
if (window.MutationObserver) {
new MutationObserver(function(mutations) {
forEach.call(mutations, function(mutation) {
forEach.call(mutation.addedNodes, setAccessibilityAttributes);
});
}).observe(document.documentElement, {
subtree: true,
childList: true
});
} else {
document.addEventListener('DOMNodeInserted', function(event) {
setAccessibilityAttributes(event.target);
});
}
}
function setAccessibilityAttributes(root) {
findElementsWithTagName(root, 'SUMMARY').forEach(function(summary) {
var details = findClosestElementWithTagName(summary, 'DETAILS');
summary.setAttribute('aria-expanded', details.hasAttribute('open'));
if (!summary.hasAttribute('tabindex')) summary.setAttribute('tabindex', '0');
if (!summary.hasAttribute('role')) summary.setAttribute('role', 'button');
});
}
function eventIsSignificant(event) {
return !(
event.defaultPrevented ||
event.ctrlKey ||
event.metaKey ||
event.shiftKey ||
event.target.isContentEditable
);
}
function onTogglingTrigger(callback) {
addEventListener(
'click',
function(event) {
if (eventIsSignificant(event)) {
if (event.which <= 1) {
var element = findClosestElementWithTagName(event.target, 'SUMMARY');
if (element && element.parentNode && element.parentNode.tagName == 'DETAILS') {
callback(element.parentNode);
}
}
}
},
false
);
addEventListener(
'keydown',
function(event) {
if (eventIsSignificant(event)) {
if (event.keyCode == 13 || event.keyCode == 32) {
var element = findClosestElementWithTagName(event.target, 'SUMMARY');
if (element && element.parentNode && element.parentNode.tagName == 'DETAILS') {
callback(element.parentNode);
event.preventDefault();
}
}
}
},
false
);
}
function triggerToggle(element) {
var event = document.createEvent('Event');
event.initEvent('toggle', false, false);
element.dispatchEvent(event);
}
function findElementsWithTagName(root, tagName) {
return (root.tagName == tagName ? [root] : []).concat(
typeof root.getElementsByTagName == 'function' ?
slice.call(root.getElementsByTagName(tagName)) :
[]
);
}
function findClosestElementWithTagName(element, tagName) {
if (typeof element.closest == 'function') {
return element.closest(tagName);
} else {
while (element) {
if (element.tagName == tagName) {
return element;
} else {
element = element.parentNode;
}
}
}
}
})();
Expanded
Detail heading
Some random subtitle
Lorem ipsum dolor sit...
HTML markup
<details class="wmnds-details" open="true">
<summary class="wmnds-link">
Detail heading
</summary>
<div class="wmnds-details__content">
<p><strong>Some random subtitle</strong></p>
<p>Lorem ipsum dolor sit...</p>
</div>
</details>
Nunjucks markup
{% from "wmnds/components/details/_details.njk" import wmndsDetails %}
{{
wmndsDetails({
headingText: "Detail heading",
headingHTML: null,
contentText: null,
contentHTML: "<p><strong>Some random subtitle</strong></p>
<p>Lorem ipsum dolor sit...</p>",
isOpen: false
})
}}
Nunjucks properties
Name | Type | Description |
---|---|---|
headingText | string | Required. Text content for heading line. If headingHTML is supplied, this is ignored. |
headingHTML | string | Required. HTML content for heading line. |
contentText | string | Required. The text content of each section, which is hidden when the section is closed. If contentHTML is supplied, this is ignored. |
contentHTML | string | Required. The HTML content of each section, which is hidden when the section is closed. |
isOpen | boolean | If true, details will be expanded upon initial load. Defaults to false . |
Recommended javascript (browser compatible)
"use strict";
/*
Details Element Polyfill 2.4.0
Copyright © 2019 Javan Makhmali
*/
/* eslint-disable */
(function() {
'use strict';
var element = document.createElement('details');
var elementIsNative = typeof HTMLDetailsElement != 'undefined' && element instanceof HTMLDetailsElement;
var support = {
open: 'open' in element || elementIsNative,
toggle: 'ontoggle' in element
};
var styles = '\ndetails, summary {\n display: block;\n}\ndetails:not([open]) > *:not(summary) {\n display: none;\n}\nsummary::before {\n content: "►";\n padding-right: 0.3rem;\n font-size: 0.6rem;\n cursor: default;\n}\n[open] > summary::before {\n content: "▼";\n}\n';
var _ref = [],
forEach = _ref.forEach,
slice = _ref.slice;
if (!support.open) {
polyfillStyles();
polyfillProperties();
polyfillToggle();
polyfillAccessibility();
}
if (support.open && !support.toggle) {
polyfillToggleEvent();
}
function polyfillStyles() {
document.head.insertAdjacentHTML('afterbegin', '<style>' + styles + '</style>');
}
function polyfillProperties() {
var prototype = document.createElement('details').constructor.prototype;
var setAttribute = prototype.setAttribute,
removeAttribute = prototype.removeAttribute;
var open = Object.getOwnPropertyDescriptor(prototype, 'open');
Object.defineProperties(prototype, {
open: {
get: function get() {
if (this.tagName == 'DETAILS') {
return this.hasAttribute('open');
} else {
if (open && open.get) {
return open.get.call(this);
}
}
},
set: function set(value) {
if (this.tagName == 'DETAILS') {
return value ? this.setAttribute('open', '') : this.removeAttribute('open');
} else {
if (open && open.set) {
return open.set.call(this, value);
}
}
}
},
setAttribute: {
value: function value(name, _value) {
var _this = this;
var call = function call() {
return setAttribute.call(_this, name, _value);
};
if (name == 'open' && this.tagName == 'DETAILS') {
var wasOpen = this.hasAttribute('open');
var result = call();
if (!wasOpen) {
var summary = this.querySelector('summary');
if (summary) summary.setAttribute('aria-expanded', true);
triggerToggle(this);
}
return result;
}
return call();
}
},
removeAttribute: {
value: function value(name) {
var _this2 = this;
var call = function call() {
return removeAttribute.call(_this2, name);
};
if (name == 'open' && this.tagName == 'DETAILS') {
var wasOpen = this.hasAttribute('open');
var result = call();
if (wasOpen) {
var summary = this.querySelector('summary');
if (summary) summary.setAttribute('aria-expanded', false);
triggerToggle(this);
}
return result;
}
return call();
}
}
});
}
function polyfillToggle() {
onTogglingTrigger(function(element) {
element.hasAttribute('open') ? element.removeAttribute('open') : element.setAttribute('open', '');
});
}
function polyfillToggleEvent() {
if (window.MutationObserver) {
new MutationObserver(function(mutations) {
forEach.call(mutations, function(mutation) {
var target = mutation.target,
attributeName = mutation.attributeName;
if (target.tagName == 'DETAILS' && attributeName == 'open') {
triggerToggle(target);
}
});
}).observe(document.documentElement, {
attributes: true,
subtree: true
});
} else {
onTogglingTrigger(function(element) {
var wasOpen = element.getAttribute('open');
setTimeout(function() {
var isOpen = element.getAttribute('open');
if (wasOpen != isOpen) {
triggerToggle(element);
}
}, 1);
});
}
}
function polyfillAccessibility() {
setAccessibilityAttributes(document);
if (window.MutationObserver) {
new MutationObserver(function(mutations) {
forEach.call(mutations, function(mutation) {
forEach.call(mutation.addedNodes, setAccessibilityAttributes);
});
}).observe(document.documentElement, {
subtree: true,
childList: true
});
} else {
document.addEventListener('DOMNodeInserted', function(event) {
setAccessibilityAttributes(event.target);
});
}
}
function setAccessibilityAttributes(root) {
findElementsWithTagName(root, 'SUMMARY').forEach(function(summary) {
var details = findClosestElementWithTagName(summary, 'DETAILS');
summary.setAttribute('aria-expanded', details.hasAttribute('open'));
if (!summary.hasAttribute('tabindex')) summary.setAttribute('tabindex', '0');
if (!summary.hasAttribute('role')) summary.setAttribute('role', 'button');
});
}
function eventIsSignificant(event) {
return !(event.defaultPrevented || event.ctrlKey || event.metaKey || event.shiftKey || event.target.isContentEditable);
}
function onTogglingTrigger(callback) {
addEventListener('click', function(event) {
if (eventIsSignificant(event)) {
if (event.which <= 1) {
var element = findClosestElementWithTagName(event.target, 'SUMMARY');
if (element && element.parentNode && element.parentNode.tagName == 'DETAILS') {
callback(element.parentNode);
}
}
}
}, false);
addEventListener('keydown', function(event) {
if (eventIsSignificant(event)) {
if (event.keyCode == 13 || event.keyCode == 32) {
var element = findClosestElementWithTagName(event.target, 'SUMMARY');
if (element && element.parentNode && element.parentNode.tagName == 'DETAILS') {
callback(element.parentNode);
event.preventDefault();
}
}
}
}, false);
}
function triggerToggle(element) {
var event = document.createEvent('Event');
event.initEvent('toggle', false, false);
element.dispatchEvent(event);
}
function findElementsWithTagName(root, tagName) {
return (root.tagName == tagName ? [root] : []).concat(typeof root.getElementsByTagName == 'function' ? slice.call(root.getElementsByTagName(tagName)) : []);
}
function findClosestElementWithTagName(element, tagName) {
if (typeof element.closest == 'function') {
return element.closest(tagName);
} else {
while (element) {
if (element.tagName == tagName) {
return element;
} else {
element = element.parentNode;
}
}
}
}
})();
Recommended javascript (ES6)
/*
Details Element Polyfill 2.4.0
Copyright © 2019 Javan Makhmali
*/
/* eslint-disable */
(function() {
'use strict';
var element = document.createElement('details');
var elementIsNative =
typeof HTMLDetailsElement != 'undefined' && element instanceof HTMLDetailsElement;
var support = {
open: 'open' in element || elementIsNative,
toggle: 'ontoggle' in element
};
var styles =
'\ndetails, summary {\n display: block;\n}\ndetails:not([open]) > *:not(summary) {\n display: none;\n}\nsummary::before {\n content: "►";\n padding-right: 0.3rem;\n font-size: 0.6rem;\n cursor: default;\n}\n[open] > summary::before {\n content: "▼";\n}\n';
var _ref = [],
forEach = _ref.forEach,
slice = _ref.slice;
if (!support.open) {
polyfillStyles();
polyfillProperties();
polyfillToggle();
polyfillAccessibility();
}
if (support.open && !support.toggle) {
polyfillToggleEvent();
}
function polyfillStyles() {
document.head.insertAdjacentHTML('afterbegin', '<style>' + styles + '</style>');
}
function polyfillProperties() {
var prototype = document.createElement('details').constructor.prototype;
var setAttribute = prototype.setAttribute,
removeAttribute = prototype.removeAttribute;
var open = Object.getOwnPropertyDescriptor(prototype, 'open');
Object.defineProperties(prototype, {
open: {
get: function get() {
if (this.tagName == 'DETAILS') {
return this.hasAttribute('open');
} else {
if (open && open.get) {
return open.get.call(this);
}
}
},
set: function set(value) {
if (this.tagName == 'DETAILS') {
return value ? this.setAttribute('open', '') : this.removeAttribute('open');
} else {
if (open && open.set) {
return open.set.call(this, value);
}
}
}
},
setAttribute: {
value: function value(name, _value) {
var _this = this;
var call = function call() {
return setAttribute.call(_this, name, _value);
};
if (name == 'open' && this.tagName == 'DETAILS') {
var wasOpen = this.hasAttribute('open');
var result = call();
if (!wasOpen) {
var summary = this.querySelector('summary');
if (summary) summary.setAttribute('aria-expanded', true);
triggerToggle(this);
}
return result;
}
return call();
}
},
removeAttribute: {
value: function value(name) {
var _this2 = this;
var call = function call() {
return removeAttribute.call(_this2, name);
};
if (name == 'open' && this.tagName == 'DETAILS') {
var wasOpen = this.hasAttribute('open');
var result = call();
if (wasOpen) {
var summary = this.querySelector('summary');
if (summary) summary.setAttribute('aria-expanded', false);
triggerToggle(this);
}
return result;
}
return call();
}
}
});
}
function polyfillToggle() {
onTogglingTrigger(function(element) {
element.hasAttribute('open') ?
element.removeAttribute('open') :
element.setAttribute('open', '');
});
}
function polyfillToggleEvent() {
if (window.MutationObserver) {
new MutationObserver(function(mutations) {
forEach.call(mutations, function(mutation) {
var target = mutation.target,
attributeName = mutation.attributeName;
if (target.tagName == 'DETAILS' && attributeName == 'open') {
triggerToggle(target);
}
});
}).observe(document.documentElement, {
attributes: true,
subtree: true
});
} else {
onTogglingTrigger(function(element) {
var wasOpen = element.getAttribute('open');
setTimeout(function() {
var isOpen = element.getAttribute('open');
if (wasOpen != isOpen) {
triggerToggle(element);
}
}, 1);
});
}
}
function polyfillAccessibility() {
setAccessibilityAttributes(document);
if (window.MutationObserver) {
new MutationObserver(function(mutations) {
forEach.call(mutations, function(mutation) {
forEach.call(mutation.addedNodes, setAccessibilityAttributes);
});
}).observe(document.documentElement, {
subtree: true,
childList: true
});
} else {
document.addEventListener('DOMNodeInserted', function(event) {
setAccessibilityAttributes(event.target);
});
}
}
function setAccessibilityAttributes(root) {
findElementsWithTagName(root, 'SUMMARY').forEach(function(summary) {
var details = findClosestElementWithTagName(summary, 'DETAILS');
summary.setAttribute('aria-expanded', details.hasAttribute('open'));
if (!summary.hasAttribute('tabindex')) summary.setAttribute('tabindex', '0');
if (!summary.hasAttribute('role')) summary.setAttribute('role', 'button');
});
}
function eventIsSignificant(event) {
return !(
event.defaultPrevented ||
event.ctrlKey ||
event.metaKey ||
event.shiftKey ||
event.target.isContentEditable
);
}
function onTogglingTrigger(callback) {
addEventListener(
'click',
function(event) {
if (eventIsSignificant(event)) {
if (event.which <= 1) {
var element = findClosestElementWithTagName(event.target, 'SUMMARY');
if (element && element.parentNode && element.parentNode.tagName == 'DETAILS') {
callback(element.parentNode);
}
}
}
},
false
);
addEventListener(
'keydown',
function(event) {
if (eventIsSignificant(event)) {
if (event.keyCode == 13 || event.keyCode == 32) {
var element = findClosestElementWithTagName(event.target, 'SUMMARY');
if (element && element.parentNode && element.parentNode.tagName == 'DETAILS') {
callback(element.parentNode);
event.preventDefault();
}
}
}
},
false
);
}
function triggerToggle(element) {
var event = document.createEvent('Event');
event.initEvent('toggle', false, false);
element.dispatchEvent(event);
}
function findElementsWithTagName(root, tagName) {
return (root.tagName == tagName ? [root] : []).concat(
typeof root.getElementsByTagName == 'function' ?
slice.call(root.getElementsByTagName(tagName)) :
[]
);
}
function findClosestElementWithTagName(element, tagName) {
if (typeof element.closest == 'function') {
return element.closest(tagName);
} else {
while (element) {
if (element.tagName == tagName) {
return element;
} else {
element = element.parentNode;
}
}
}
}
})();