diff options
| author | BigCoke233 <hi@guhub.cn> | 2020-05-30 14:30:38 +0800 |
|---|---|---|
| committer | BigCoke233 <hi@guhub.cn> | 2020-05-30 14:30:38 +0800 |
| commit | bd0a23b052dc750db72d2b98349044a56ede2419 (patch) | |
| tree | e9b1b5540f639e438bd461bec1e8bf9e9a3f0038 /assets | |
| parent | 33811859eb3438db65958e9a612918643786cdeb (diff) | |
✨ Add: 支持解析 details 短代码,并使用 js 垫片优化兼容性
Diffstat (limited to 'assets')
| -rw-r--r-- | assets/css/main/post.css | 7 | ||||
| -rw-r--r-- | assets/js/details-element-polyfill.js | 194 |
2 files changed, 201 insertions, 0 deletions
diff --git a/assets/css/main/post.css b/assets/css/main/post.css index 6aaeff2..6a5728b 100644 --- a/assets/css/main/post.css +++ b/assets/css/main/post.css @@ -281,6 +281,13 @@ .post-content ol ul {
margin-top: 0;
}
+.post-content summary {
+ outline: none;
+ cursor: pointer;
+}
+.post-content summary:hover {
+ font-weight: bolder
+}
/* 加密文章 */
.post-content .protected {
display: flex;
diff --git a/assets/js/details-element-polyfill.js b/assets/js/details-element-polyfill.js new file mode 100644 index 0000000..b651dfc --- /dev/null +++ b/assets/js/details-element-polyfill.js @@ -0,0 +1,194 @@ +/* +Details Element Polyfill 2.4.0 +Copyright © 2019 Javan Makhmali + */ +(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; + } + } + } + } + })();
\ No newline at end of file |
