Vant 组件看板 (2.x)

更方便的查看 Vant 组件

当前为 2020-07-23 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name:zh-CN Vant 组件看板 (2.x)
  3. // @name Vant Components Dashboard (2.x)
  4. // @namespace https://github.com/xianghongai/Tampermonkey-UserScript
  5. // @version 0.0.1
  6. // @description:zh-CN 更方便的查看 Vant 组件
  7. // @description Better view for Vant Component
  8. // @author Nicholas Hsiang / 山茶树和葡萄树
  9. // @icon https://xinlu.ink/favicon.ico
  10. // @match https://youzan.github.io/vant/*
  11. // @grant none
  12. // ==/UserScript==
  13. (function () {
  14. "use strict";
  15.  
  16. const titleText = "Vant";
  17.  
  18. const gridSelector = ".van-doc-nav__group+.van-doc-nav__group";
  19. const girdIsList = true; // 如果提取的是一个 Node 数组
  20. // 基于 gridSelector 做 querySelectorAll,添加 hs-dashboard__column 样式名
  21. const columnSelector = ".van-doc-nav__group";
  22. // 基于 gridSelector 做 querySelectorAll,添加 hs-dashboard__item-title 样式名
  23. const columnTitleSelector = ".van-doc-nav__title";
  24. // 基于 gridSelector 做 querySelectorAll,添加 hs-dashboard__list 样式名
  25. const menuListSelector = ".van-doc-nav__group";
  26. // 基于 gridSelector 做 querySelectorAll,添加 hs-dashboard__item 样式名,这一层尽量在 li 标签上
  27. const menuItemSelector = ".van-doc-nav__item";
  28.  
  29. const menuItemActionSelector = ".van-doc-nav__item .active";
  30.  
  31. const helpEnable = true;
  32. const helpSelector = "#api";
  33.  
  34. // 使用本扩展的样式风格,将会替换原站点的菜单风格
  35. const customStyleEnable = true; // Dark & Light
  36. const cloneNodeEnable = true; // 保留原 DOM 节点?
  37.  
  38. function initialExtraStyle() {
  39. return `
  40. .hs-dashboard__list .hs-dashboard__title { margin-left: 2px; }
  41. .hs-dashboard__toggle { top: 5px; right: 20px; }
  42. .hs-dashboard__grid { justify-content: space-around; /* center | space-evenly | space-between */ }
  43. `;
  44. }
  45.  
  46. /* ------------------------------------------------------------------------- */
  47.  
  48. let wrapperEle = null;
  49. let themeSwitchEle = null;
  50. let themeSwitchForm = null;
  51.  
  52. const bodyContainer = document.querySelector("body");
  53.  
  54. function initialDashboard() {
  55. initialToggle();
  56. initialStyle(initialExtraStyle);
  57. initialMenu(cloneNodeEnable);
  58. initialHelp();
  59. handleEvent();
  60. handleTheme(true);
  61. }
  62.  
  63. let interval = null;
  64.  
  65. function ready() {
  66. const originEle = document.querySelector(gridSelector);
  67.  
  68. if (originEle) {
  69. clearInterval(interval);
  70. // Dashboard
  71. initialDashboard();
  72. // Other
  73. }
  74. }
  75.  
  76. interval = setInterval(ready, 1000);
  77.  
  78. // #region MENU
  79. /** 生成 Menu */
  80. function initialMenu(clone) {
  81. // Wrapper
  82. wrapperEle = document.createElement("section");
  83. wrapperEle.classList.add("hs-dashboard__wrapper", "hs-hide");
  84.  
  85. if (customStyleEnable) {
  86. wrapperEle.setAttribute("id", "hs-dashboard");
  87. }
  88.  
  89. // Header
  90. const headerEle = document.createElement("header");
  91. headerEle.classList.add("hs-dashboard__header");
  92.  
  93. // Title → Header
  94. const titleEle = document.createElement("h1");
  95. titleEle.classList.add("hs-dashboard__title");
  96. titleEle.innerText = titleText || "";
  97. headerEle.appendChild(titleEle);
  98.  
  99. // Theme → Header
  100. if (customStyleEnable) {
  101. const themeEle = document.createElement("div");
  102. themeEle.classList.add("hs-theme-switch");
  103. themeEle.innerHTML = initialThemeTpl();
  104. headerEle.appendChild(themeEle);
  105. }
  106.  
  107. // Menu
  108. const containerEle = document.createElement("div");
  109. containerEle.classList.add("hs-dashboard__container");
  110.  
  111. // 1. 先从页面上获取 DOM 生成 gird
  112. let gridEle = null;
  113. let nodeTemp = null;
  114.  
  115. if (girdIsList) {
  116. gridEle = document.createElement("div");
  117. const gridListEle = document.querySelectorAll(gridSelector);
  118. gridListEle &&
  119. gridListEle.forEach((element) => {
  120. nodeTemp = clone ? element.cloneNode(true) : element;
  121. gridEle.appendChild(nodeTemp);
  122. });
  123. } else {
  124. nodeTemp = document.querySelector(gridSelector);
  125. gridEle = clone ? nodeTemp.cloneNode(true) : nodeTemp;
  126. gridEle && nodeTemp.removeAttribute("id");
  127. }
  128.  
  129. gridEle.classList.add("hs-dashboard__grid"); // 追加新的样式
  130.  
  131. // Menu → Container
  132. containerEle.appendChild(gridEle);
  133.  
  134. // 2. 内部元素追加新的样式
  135. // 2.1 column
  136. const columnEle = containerEle.querySelectorAll(columnSelector);
  137. columnEle.forEach((element) => {
  138. element.classList.add("hs-dashboard__column");
  139. });
  140.  
  141. // 2.2 title
  142. const columnTitleEle = containerEle.querySelectorAll(columnTitleSelector);
  143. columnTitleEle.forEach((element) => {
  144. element.classList.add("hs-dashboard__title");
  145. });
  146.  
  147. // 2.3 menu list
  148. const menuListEle = containerEle.querySelectorAll(menuListSelector);
  149. menuListEle.forEach((element) => {
  150. element.classList.add("hs-dashboard__list");
  151. });
  152.  
  153. // 2.4 menu item
  154. const menuItemEle = containerEle.querySelectorAll(menuItemSelector);
  155. menuItemEle.forEach((element) => {
  156. element.classList.add("hs-dashboard__item");
  157. });
  158.  
  159. // 2.5 menu item action
  160. const actionEle = containerEle.querySelector(menuItemActionSelector);
  161. if (actionEle) {
  162. const menuItemTemp = getParents(actionEle, menuItemSelector);
  163. menuItemTemp.classList.add("hs-active");
  164. }
  165.  
  166. // header,container → wrapper
  167. wrapperEle.appendChild(headerEle);
  168. wrapperEle.appendChild(containerEle);
  169.  
  170. // wrapper → body
  171. bodyContainer.appendChild(wrapperEle);
  172. }
  173. // #endregion MENU
  174.  
  175. // #region Event
  176. /** 注册事件 */
  177. function handleEvent() {
  178. if (!wrapperEle) {
  179. wrapperEle = document.querySelector(".hs-dashboard__wrapper");
  180. }
  181.  
  182. if (!themeSwitchEle) {
  183. themeSwitchEle = document.querySelector(".hs-theme-switch");
  184. }
  185.  
  186. if (!themeSwitchForm) {
  187. themeSwitchForm = document.querySelector(".hs-theme-switch__form-control");
  188. }
  189.  
  190. bodyContainer.addEventListener("click", (event) => {
  191. const targetEle = event.target;
  192.  
  193. const itemEle = getParents(targetEle, ".hs-dashboard__item");
  194.  
  195. const isItem = hasClass(targetEle, "hs-dashboard__item");
  196.  
  197. const isItemWrapper = getParents(targetEle, ".hs-dashboard__column") && getParents(targetEle, ".hs-dashboard__list");
  198.  
  199. const isToggle = getParents(targetEle, ".hs-dashboard__toggle-menu") || hasClass(targetEle, "hs-dashboard__toggle-menu");
  200.  
  201. const isHelp = getParents(targetEle, ".hs-dashboard__toggle-help") || hasClass(targetEle, "hs-dashboard__toggle-help");
  202.  
  203. const isTheme = getParents(targetEle, ".hs-theme-switch") || hasClass(targetEle, "hs-theme-switch");
  204.  
  205. if (itemEle || isItem || isItemWrapper) {
  206. window.setTimeout(() => {
  207. clearStyle(wrapperEle);
  208. }, 300);
  209.  
  210. handleItemClick(itemEle, isItem, targetEle);
  211. } else if (isToggle) {
  212. wrapperEle.classList.toggle("hs-hide");
  213. bodyContainer.classList.toggle("hs-body-overflow_hide");
  214. } else if (isHelp) {
  215. clearStyle(wrapperEle);
  216. handleHelp();
  217. } else if (isTheme) {
  218. handleTheme();
  219. }
  220. });
  221. }
  222.  
  223. /** 导航点击 */
  224. function handleItemClick(itemEle, isItem, targetEle) {
  225. let itemTemp = null;
  226.  
  227. if (itemEle) {
  228. itemTemp = itemEle;
  229. } else if (isItem) {
  230. itemTemp = targetEle;
  231. }
  232.  
  233. if (itemTemp) {
  234. const items = wrapperEle.querySelectorAll(".hs-dashboard__item");
  235. items.forEach((element) => {
  236. element.classList.remove("hs-active");
  237. element.querySelector("a").classList.remove("active");
  238. });
  239. itemTemp.classList.add("hs-active");
  240. }
  241. }
  242.  
  243. /** 退出预览 */
  244. function clearStyle(wrapperEle) {
  245. wrapperEle.classList.add("hs-hide");
  246. bodyContainer.classList.remove("hs-body-overflow_hide");
  247. }
  248. // #endregion Event
  249.  
  250. // #region HELP
  251. /** 是否启用‘页面滚动至指定位置’ */
  252. function initialHelp() {
  253. if (!helpEnable) {
  254. const ele = document.querySelector(".hs-dashboard__toggle-help");
  255. ele.classList.add("hs-hide");
  256. }
  257. }
  258.  
  259. /** 页面滚动至指定位置 */
  260. function handleHelp() {
  261. if (!helpSelector) {
  262. return false;
  263. }
  264.  
  265. const helpEle = document.querySelector(helpSelector);
  266.  
  267. if (!helpEle) {
  268. return false;
  269. }
  270.  
  271. const top = helpEle.getBoundingClientRect().top + window.pageYOffset;
  272.  
  273. window.scrollTo({
  274. top,
  275. behavior: "smooth",
  276. });
  277. }
  278. // #endregion HELP
  279.  
  280. // #region STYLE
  281. /** 添加样式 */
  282. function initialStyle(param) {
  283. let tpl = initialStyleTpl();
  284. const headEle = document.head || document.getElementsByTagName("head")[0];
  285. const styleEle = document.createElement("style");
  286.  
  287. let str = null;
  288.  
  289. if (typeof param === "function") {
  290. str = param();
  291. } else if (typeof param === "string") {
  292. str = param;
  293. }
  294.  
  295. if (typeof str === "string") {
  296. tpl += str;
  297. }
  298.  
  299. styleEle.type = "text/css";
  300.  
  301. if (styleEle.styleSheet) {
  302. styleEle.styleSheet.cssText = tpl;
  303. } else {
  304. styleEle.appendChild(document.createTextNode(tpl));
  305. }
  306.  
  307. headEle.appendChild(styleEle);
  308. }
  309.  
  310. /** 样式表 */
  311. function initialStyleTpl() {
  312. return `
  313.  
  314. :root {
  315. --item-height: 36px;
  316. --hs-font-size-base: 15px;
  317. --hs-global-spacing: 1rem;
  318. --hs-color-primary: #1890ff;
  319. --hs-spacing-horizontal: var(--hs-global-spacing);
  320. }
  321. .hs-hide {
  322. display: none !important;
  323. }
  324.  
  325. .hs-body-overflow_hide {
  326. height: 100% !important;
  327. overflow: hidden !important;
  328. }
  329.  
  330. /* #region toggle */
  331. .hs-dashboard__toggle {
  332. position: fixed;
  333. z-index: 99999;
  334. top: 15px;
  335. right: 5px;
  336. }
  337.  
  338. .hs-dashboard__toggle-item {
  339. position: relative;
  340. width: 28px;
  341. height: 28px;
  342. margin-top: 10px;
  343. margin-bottom: 10px;
  344. overflow: hidden;
  345. line-height: 1 !important;
  346. border-radius: 50%;
  347. border: 1px solid #ccc;
  348. text-align: center;
  349. color: #555;
  350. background-color: #fff;
  351. cursor: pointer;
  352. transition: all 0.2s;
  353. }
  354.  
  355. .hs-dashboard__toggle-item:hover {
  356. border-color: #aaa;
  357. color: #111;
  358. }
  359.  
  360. .hs-dashboard__toggle-icon svg{
  361. position: absolute;
  362. top: 50%;
  363. left: 50%;
  364. z-index: 9;
  365. transform: translate(-50%, -50%);
  366. font-style: normal !important;
  367. }
  368. /* #endregion toggle */
  369.  
  370. /* #region wrapper */
  371. .hs-dashboard__wrapper {
  372. position: fixed;
  373. top: 0;
  374. right: 0;
  375. bottom: 0;
  376. left: 0;
  377. z-index: 99998;
  378. overflow-y: auto;
  379. background-color: #fff;
  380. font-size: var(--hs-font-size-base);
  381. }
  382.  
  383. .hs-dashboard__wrapper::-webkit-scrollbar {
  384. width: 8px;
  385. height: 6px;
  386. background: rgba(0, 0, 0, 0.1);
  387. }
  388.  
  389. .hs-dashboard__wrapper::-webkit-scrollbar-thumb {
  390. background: rgba(0, 0, 0, 0.3);
  391. }
  392.  
  393. .hs-dashboard__wrapper::-webkit-scrollbar-track {
  394. background: rgba(0, 0, 0, 0.1);
  395. }
  396. /* #endregion wrapper */
  397.  
  398. .hs-dashboard__header {
  399. position: relative;
  400. padding-top: 10px;
  401. text-align: center;
  402. }
  403.  
  404. .hs-dashboard__header .hs-dashboard__title {
  405. margin: 0;
  406. padding-top: 10px;
  407. padding-bottom: 10px;
  408. font-size: 1em;
  409. font-weight: normal;
  410. }
  411.  
  412. /* #region theme */
  413. .hs-theme-switch {
  414. display: flex;
  415. touch-action: pan-x;
  416. position: relative;
  417. background-color: #fff;
  418. border: 0;
  419. margin: 0;
  420. padding: 0;
  421. user-select: none;
  422. -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  423. -webkit-tap-highlight-color: transparent;
  424. cursor: pointer;
  425. }
  426.  
  427. .hs-theme-switch {
  428. width: 50px;
  429. height: 24px;
  430. padding: 0;
  431. border-radius: 30px;
  432. background-color: #4d4d4d;
  433. transition: all 0.2s ease;
  434. }
  435.  
  436. .hs-dashboard__header .hs-theme-switch {
  437. position: absolute;
  438. top: 10px;
  439. left: 10px;
  440. }
  441.  
  442. .hs-theme-switch__style {
  443. position: relative;
  444. width: 24px;
  445. height: 24px;
  446. line-height: 1;
  447. font-size: 20px;
  448. text-align: center;
  449. }
  450.  
  451. .hs-theme-switch__icon svg {
  452. position: absolute;
  453. top: 50%;
  454. left: 50%;
  455. transform: translate(-50%, -50%);
  456. }
  457.  
  458. .hs-theme-switch__thumb {
  459. position: absolute;
  460. top: 1px;
  461. left: 1px;
  462. width: 22px;
  463. height: 22px;
  464. border: 1px solid #ff7938;
  465. border-radius: 50%;
  466. background-color: #fafafa;
  467. box-sizing: border-box;
  468. transition: all 0.25s ease;
  469. }
  470.  
  471. .hs-theme-switch_checked .hs-theme-switch__thumb {
  472. left: 27px;
  473. border-color: #4d4d4d;
  474. }
  475.  
  476. .hs-toggle-screenreader-only {
  477. border: 0;
  478. clip: rect(0 0 0 0);
  479. height: 1px;
  480. margin: -1px;
  481. overflow: hidden;
  482. padding: 0;
  483. position: absolute;
  484. width: 1px;
  485. }
  486. /* #endregion theme */
  487.  
  488. /* #region grid */
  489. .hs-dashboard__grid {
  490. display: flex;
  491. justify-content: space-evenly;
  492. margin: 0;
  493. padding: 0;
  494. list-style: none;
  495. }
  496.  
  497. .hs-dashboard__column {
  498. padding-right: 10px;
  499. padding-left: 10px;
  500. }
  501.  
  502. .hs-dashboard__column a {
  503. display: block;
  504. padding-left: 20px !important;
  505. padding-right: 40px !important;
  506. text-decoration: none;
  507. }
  508.  
  509. .hs-dashboard__container ul {
  510. padding: 0;
  511. }
  512.  
  513. .hs-dashboard__container li {
  514. padding-left: 0 !important;
  515. list-style: none;
  516. }
  517.  
  518. .hs-dashboard__column .hs-dashboard__title {
  519. display: block;
  520. padding-left: var(--hs-spacing-horizontal) !important;
  521. padding-right: calc(var(--hs-spacing-horizontal) * 2) !important;
  522. text-align: left;
  523. margin-top: 10px !important;
  524. }
  525.  
  526. .hs-dashboard__column .hs-dashboard__list {
  527. margin-top: 10px !important;
  528. }
  529.  
  530. .hs-dashboard__column .hs-dashboard__list .hs-dashboard__item {
  531. margin: 0 !important;
  532. padding-left: 0 !important;
  533. padding-right: 0 !important;
  534. height: var(--item-height);
  535. line-height: var(--item-height);
  536. }
  537. /* #endregion grid */
  538.  
  539. /* #region custom */
  540. #hs-dashboard.hs-dashboard__wrapper {
  541. transition: all 0.2s ease;
  542. }
  543.  
  544. #hs-dashboard .hs-dashboard__column .hs-dashboard__title {
  545. font-size: 14px;
  546. line-height: 1.5715;
  547. color: rgba(0, 0, 0, 0.45);
  548. }
  549.  
  550. #hs-dashboard a {
  551. overflow: hidden;
  552. white-space: nowrap;
  553. font-size: 14px;
  554. text-overflow: ellipsis;
  555. text-decoration: none;
  556. color: rgba(0, 0, 0, 0.85);
  557. transition: color 0.3s ease;
  558. }
  559.  
  560. #hs-dashboard a:hover {
  561. color: var(--hs-color-primary);
  562. text-decoration: none;
  563. outline: 0;
  564. }
  565.  
  566. /* light */
  567. #hs-dashboard.hs-dashboard__wrapper_light {
  568. color: #161616;
  569. background-color: #fff;
  570. }
  571.  
  572. /* dark */
  573. #hs-dashboard.hs-dashboard__wrapper_dark {
  574. color: #fff;
  575. background-color: #161616;
  576. }
  577.  
  578. #hs-dashboard.hs-dashboard__wrapper_dark .hs-dashboard__title {
  579. font-weight: bold;
  580. color: #fff;
  581. }
  582.  
  583. #hs-dashboard.hs-dashboard__wrapper_dark a {
  584. color: #fff;
  585. }
  586.  
  587. #hs-dashboard.hs-dashboard__wrapper_dark a:hover {
  588. color: var(--hs-color-primary);
  589. }
  590.  
  591. #hs-dashboard .hs-dashboard__item.active,
  592. #hs-dashboard .hs-dashboard__item.active a,
  593. #hs-dashboard .hs-dashboard__item .active,
  594. #hs-dashboard .hs-dashboard__item.hs-active,
  595. #hs-dashboard .hs-dashboard__item.hs-active a {
  596. color: var(--hs-color-primary);
  597. }
  598.  
  599. #hs-dashboard .hs-dashboard__item.hs-active {
  600. background-color: #e6f7ff;
  601. }
  602.  
  603. #hs-dashboard .hs-dashboard__item {
  604. position: relative;
  605. }
  606.  
  607. #hs-dashboard .hs-dashboard__item::after {
  608. content: ' ';
  609. position: absolute;
  610. top: 0;
  611. right: 0;
  612. bottom: 0;
  613. border-right: 3px solid var(--hs-color-primary);
  614. transform: scaleY(0.0001);
  615. transition: transform 0.15s cubic-bezier(0.215, 0.61, 0.355, 1),
  616. opacity 0.15s cubic-bezier(0.215, 0.61, 0.355, 1),
  617. -webkit-transform 0.15s cubic-bezier(0.215, 0.61, 0.355, 1);
  618. opacity: 0;
  619. }
  620.  
  621. #hs-dashboard .hs-dashboard__item.hs-active::after {
  622. transform: scaleY(1);
  623. opacity: 1;
  624. transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1),
  625. opacity 0.15s cubic-bezier(0.645, 0.045, 0.355, 1),
  626. -webkit-transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1);
  627. }
  628. /* #endregion custom */
  629.  
  630. `;
  631. }
  632. // #endregion STYLE
  633.  
  634. // #region TOGGLE
  635. /** 生成 Dashboard 开关 */
  636. function initialToggle() {
  637. const tpl = initialToggleTpl();
  638. const ele = document.createElement("section");
  639. // ele.className = 'hs-dashboard__toggle';
  640. // ele.setAttribute("class", "hs-dashboard__toggle");
  641. ele.classList.add("hs-dashboard__toggle");
  642. ele.innerHTML = tpl;
  643.  
  644. // toggle → body
  645. bodyContainer.appendChild(ele);
  646. }
  647. /** Dashboard 开关 DOM */
  648. function initialToggleTpl() {
  649. return `
  650. <!-- menu -->
  651. <div class="hs-dashboard__toggle-item hs-dashboard__toggle-menu">
  652. <i class="hs-dashboard__toggle-icon">
  653. <svg
  654. viewBox="64 64 896 896"
  655. focusable="false"
  656. data-icon="appstore"
  657. width="1em"
  658. height="1em"
  659. fill="currentColor"
  660. aria-hidden="true"
  661. >
  662. <path
  663. d="M464 144H160c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V160c0-8.8-7.2-16-16-16zm-52 268H212V212h200v200zm452-268H560c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V160c0-8.8-7.2-16-16-16zm-52 268H612V212h200v200zM464 544H160c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V560c0-8.8-7.2-16-16-16zm-52 268H212V612h200v200zm452-268H560c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V560c0-8.8-7.2-16-16-16zm-52 268H612V612h200v200z"
  664. ></path>
  665. </svg>
  666. </i>
  667. </div>
  668. <!-- api -->
  669. <div class="hs-dashboard__toggle-item hs-dashboard__toggle-help">
  670. <i class="hs-dashboard__toggle-icon">
  671. <svg
  672. viewBox="64 64 896 896"
  673. focusable="false"
  674. class=""
  675. data-icon="bulb"
  676. width="1em"
  677. height="1em"
  678. fill="currentColor"
  679. aria-hidden="true"
  680. >
  681. <path
  682. d="M632 888H392c-4.4 0-8 3.6-8 8v32c0 17.7 14.3 32 32 32h192c17.7 0 32-14.3 32-32v-32c0-4.4-3.6-8-8-8zM512 64c-181.1 0-328 146.9-328 328 0 121.4 66 227.4 164 284.1V792c0 17.7 14.3 32 32 32h264c17.7 0 32-14.3 32-32V676.1c98-56.7 164-162.7 164-284.1 0-181.1-146.9-328-328-328zm127.9 549.8L604 634.6V752H420V634.6l-35.9-20.8C305.4 568.3 256 484.5 256 392c0-141.4 114.6-256 256-256s256 114.6 256 256c0 92.5-49.4 176.3-128.1 221.8z"
  683. ></path>
  684. </svg>
  685. </i>
  686. </div>
  687. `;
  688. }
  689. // #endregion TOGGLE
  690.  
  691. // #region THEME
  692. function handleTheme(isInit) {
  693. if (isInit) {
  694. const theme = localStorage.getItem("hs_dashboard_theme");
  695.  
  696. if (theme && theme === "dark") {
  697. themeSwitchForm.checked = true;
  698. } else {
  699. themeSwitchForm.checked = false;
  700. }
  701. } else {
  702. themeSwitchForm.click();
  703. }
  704.  
  705. const checked = themeSwitchForm.checked;
  706.  
  707. if (checked) {
  708. localStorage.setItem("hs_dashboard_theme", "dark");
  709. wrapperEle.classList.add("hs-dashboard__wrapper_dark");
  710. wrapperEle.classList.remove("hs-dashboard__wrapper_light");
  711. themeSwitchEle.classList.add("hs-theme-switch_checked");
  712. } else {
  713. localStorage.setItem("hs_dashboard_theme", "light");
  714. wrapperEle.classList.add("hs-dashboard__wrapper_light");
  715. wrapperEle.classList.remove("hs-dashboard__wrapper_dark");
  716. themeSwitchEle.classList.remove("hs-theme-switch_checked");
  717. }
  718. }
  719.  
  720. function initialThemeTpl() {
  721. return `
  722. <input type="checkbox" class="hs-toggle-screenreader-only hs-theme-switch__form-control" title="Dark mode" />
  723. <div class="hs-theme-switch__style hs-theme-switch__style_dark">
  724. <i class="hs-theme-switch__icon">
  725. <svg
  726. t="1588325093630"
  727. class="icon"
  728. viewBox="0 0 1024 1024"
  729. version="1.1"
  730. xmlns="http://www.w3.org/2000/svg"
  731. p-id="11008"
  732. width="1em"
  733. height="1em"
  734. >
  735. <path
  736. d="M483.555556 964.266667c-164.977778 0-315.733333-85.333333-398.222223-224.711111 19.911111 2.844444 39.822222 2.844444 56.888889 2.844444 275.911111 0 500.622222-224.711111 500.622222-500.622222 0-68.266667-14.222222-133.688889-39.822222-193.422222 201.955556 54.044444 347.022222 238.933333 347.022222 449.422222 0 256-210.488889 466.488889-466.488888 466.488889z"
  737. fill="#F7FF53"
  738. p-id="11009"
  739. ></path>
  740. <path
  741. d="M631.466667 73.955556c179.2 62.577778 301.511111 230.4 301.511111 423.822222 0 247.466667-201.955556 449.422222-449.422222 449.422222-147.911111 0-281.6-71.111111-364.088889-187.733333H142.222222c284.444444 0 517.688889-233.244444 517.688889-517.688889 0-56.888889-8.533333-113.777778-28.444444-167.822222M571.733333 22.755556C605.866667 88.177778 625.777778 162.133333 625.777778 241.777778c0 267.377778-216.177778 483.555556-483.555556 483.555555-31.288889 0-59.733333-2.844444-88.177778-8.533333 79.644444 156.444444 241.777778 264.533333 429.511112 264.533333 267.377778 0 483.555556-216.177778 483.555555-483.555555C967.111111 261.688889 796.444444 65.422222 571.733333 22.755556z"
  742. fill="#303133"
  743. p-id="11010"
  744. ></path>
  745. <path
  746. d="M787.911111 455.111111c-5.688889-2.844444-8.533333-8.533333-5.688889-14.222222 5.688889-17.066667-2.844444-42.666667-19.911111-48.355556-17.066667-5.688889-39.822222 8.533333-45.511111 22.755556-2.844444 5.688889-8.533333 8.533333-14.222222 5.688889-5.688889-2.844444-8.533333-8.533333-5.688889-14.222222 8.533333-25.6 42.666667-45.511111 73.955555-34.133334 28.444444 11.377778 39.822222 48.355556 31.288889 73.955556-2.844444 5.688889-8.533333 8.533333-14.222222 8.533333"
  747. fill="#303133"
  748. p-id="11011"
  749. ></path>
  750. <path
  751. d="M608.711111 620.088889c-14.222222 0-28.444444-2.844444-39.822222-11.377778-31.288889-22.755556-31.288889-65.422222-31.288889-68.266667 0-8.533333 8.533333-17.066667 17.066667-17.066666s17.066667 8.533333 17.066666 17.066666 2.844444 31.288889 17.066667 39.822223c11.377778 8.533333 25.6 8.533333 45.511111 0 8.533333-2.844444 19.911111 2.844444 22.755556 11.377777 2.844444 8.533333-2.844444 19.911111-11.377778 22.755556-14.222222 2.844444-25.6 5.688889-36.977778 5.688889zM571.733333 540.444444z"
  752. fill="#FF2929"
  753. p-id="11012"
  754. ></path>
  755. <path
  756. d="M810.666667 588.8c-5.688889 19.911111-36.977778 28.444444-68.266667 19.911111-31.288889-8.533333-54.044444-34.133333-48.355556-54.044444 5.688889-19.911111 36.977778-28.444444 68.266667-19.911111 34.133333 11.377778 54.044444 34.133333 48.355556 54.044444"
  757. fill="#FFA450"
  758. p-id="11013"
  759. ></path>
  760. <path
  761. d="M864.711111 270.222222c14.222222 42.666667 19.911111 91.022222 19.911111 136.533334 0 258.844444-213.333333 466.488889-477.866666 466.488888-96.711111 0-187.733333-28.444444-264.533334-76.8 82.488889 93.866667 204.8 156.444444 344.177778 156.444445C736.711111 952.888889 938.666667 756.622222 938.666667 512c0-88.177778-28.444444-173.511111-73.955556-241.777778z"
  762. fill="#FF7938"
  763. p-id="11014"
  764. ></path>
  765. </svg>
  766. </i>
  767. </div>
  768. <div class="hs-theme-switch__style hs-theme-switch__style_light">
  769. <i class="hs-theme-switch__icon">
  770. <svg
  771. t="1588324703446"
  772. class="icon"
  773. viewBox="0 0 1024 1024"
  774. version="1.1"
  775. xmlns="http://www.w3.org/2000/svg"
  776. p-id="6232"
  777. width="1em"
  778. height="1em"
  779. >
  780. <path
  781. d="M792.35 835.94l-128.09-30.32c-17.73-4.2-36.12 3.66-45.34 19.37l-66.64 113.52c-15.83 26.97-54.67 27.4-71.1 0.79l-69.14-112.02c-9.57-15.5-28.13-22.95-45.76-18.36l-127.39 33.15c-30.26 7.88-58.03-19.29-50.83-49.72l30.32-128.09c4.2-17.73-3.66-36.12-19.37-45.34L85.49 552.28c-26.97-15.83-27.4-54.67-0.79-71.1l112.02-69.14c15.5-9.57 22.95-28.13 18.36-45.76l-33.15-127.39c-7.88-30.26 19.29-58.03 49.72-50.83l128.09 30.32c17.73 4.2 36.12-3.66 45.34-19.37l66.64-113.52c15.83-26.97 54.67-27.4 71.1-0.79l69.14 112.02c9.57 15.5 28.13 22.95 45.76 18.36l127.39-33.15c30.26-7.88 58.03 19.29 50.83 49.72l-30.32 128.09c-4.2 17.73 3.66 36.12 19.37 45.34l113.52 66.64c26.97 15.83 27.4 54.67 0.79 71.1l-112.02 69.14c-15.5 9.57-22.95 28.13-18.36 45.76l33.15 127.39c7.88 30.26-19.29 58.03-49.72 50.83z"
  782. fill="#FF7938"
  783. p-id="6233"
  784. ></path>
  785. <path
  786. d="M512 512m-207.66 0a207.66 207.66 0 1 0 415.32 0 207.66 207.66 0 1 0-415.32 0Z"
  787. fill="#F7FF53"
  788. p-id="6234"
  789. ></path>
  790. <path
  791. d="M442.78 468.74m-25.96 0a25.96 25.96 0 1 0 51.92 0 25.96 25.96 0 1 0-51.92 0Z"
  792. fill="#303133"
  793. p-id="6235"
  794. ></path>
  795. <path
  796. d="M581.22 468.74m-25.96 0a25.96 25.96 0 1 0 51.92 0 25.96 25.96 0 1 0-51.92 0Z"
  797. fill="#303133"
  798. p-id="6236"
  799. ></path>
  800. <path
  801. d="M442.78 582.02s17.31 48.31 69.22 48.31 69.22-48.31 69.22-48.31H442.78z"
  802. fill="#FF2929"
  803. p-id="6237"
  804. ></path>
  805. </svg>
  806. </i>
  807. </div>
  808. <div class="hs-theme-switch__thumb"></div>
  809. `;
  810. }
  811. // #endregion THEME
  812.  
  813. // #region COMMON
  814. function hasClass(el, className) {
  815. if (el.classList) {
  816. return el.classList.contains(className);
  817. } else {
  818. return !!el.className.match(new RegExp("(\\s|^)" + className + "(\\s|$)"));
  819. }
  820. }
  821.  
  822. function getParents(elem, selector) {
  823. // Element.matches() polyfill
  824. if (!Element.prototype.matches) {
  825. Element.prototype.matches =
  826. Element.prototype.matchesSelector ||
  827. Element.prototype.mozMatchesSelector ||
  828. Element.prototype.msMatchesSelector ||
  829. Element.prototype.oMatchesSelector ||
  830. Element.prototype.webkitMatchesSelector ||
  831. function (s) {
  832. var matches = (this.document || this.ownerDocument).querySelectorAll(s),
  833. i = matches.length;
  834. while (--i >= 0 && matches.item(i) !== this) {}
  835. return i > -1;
  836. };
  837. }
  838.  
  839. // Get the closest matching element
  840. for (; elem && elem !== document; elem = elem.parentNode) {
  841. if (elem.matches(selector)) return elem;
  842. }
  843. return null;
  844. }
  845. // #endregion
  846. })();