- // ==UserScript==
- // @name ESJ Zone: Auto Expand Collapsed Chapters
- // @name:zh-TW ESJ Zone:自動展開摺疊章節
- // @name:zh-CN ESJ Zone:自动展开折叠章节
- // @description Expand the collapsed, last read chapters (alternatively, all chapters) automatically.
- // @description:zh-TW 自動展開已折疊的最後閱讀章節(或展開所有章節)。
- // @description:zh-CN 自动展开已折叠的最后阅读章节(或展开所有章节)。
- // @icon https://icons.duckduckgo.com/ip3/www.esjzone.cc.ico
- // @author Jason Kwok
- // @namespace https://jasonhk.dev/
- // @version 1.1.4
- // @license MIT
- // @match https://www.esjzone.cc/detail/*.html
- // @match https://www.esjzone.me/detail/*.html
- // @run-at document-end
- // @grant GM.getValue
- // @grant GM.setValue
- // @grant GM.registerMenuCommand
- // @require https://unpkg.com/typesafe-i18n@5.26.2/dist/i18n.object.min.js
- // @require https://unpkg.com/uuid-random@1.3.2/uuid-random.min.js
- // @supportURL https://greasyfork.org/scripts/487306/feedback
- // ==/UserScript==
-
- const LL = (function()
- {
- const translations =
- {
- "en": {
- COMMAND: {
- SETTING: "Change Expand Setting",
- },
- SETTING: {
- TITLE: "Expand Setting",
- EXPAND_BEHAVIOUR: "Expand Behaviour",
- EXPAND_ALL: "Expand All Chapters",
- LAST_READ: "Last Read Chapters Only",
- CANCEL: "Cancel",
- SAVE: "Save",
- },
- },
- "zh-TW": {
- COMMAND: {
- SETTING: "更改展開設定",
- },
- SETTING: {
- TITLE: "展開設定",
- EXPAND_BEHAVIOUR: "展開行為",
- EXPAND_ALL: "展開所有章節",
- LAST_READ: "展開最後閱讀章節",
- CANCEL: "取消",
- SAVE: "儲存",
- },
- },
- "zh-CN": {
- COMMAND: {
- SETTING: "更改展開设定",
- },
- SETTING: {
- TITLE: "展開设定",
- EXPAND_BEHAVIOUR: "展开行为",
- EXPAND_ALL: "展开所有章节",
- LAST_READ: "展开最后阅读章节",
- CANCEL: "取消",
- SAVE: "储存",
- },
- },
- };
-
- let locale = "en";
- for (let _locale of navigator.languages.map((language) => new Intl.Locale(language)))
- {
- if (_locale.language === "zh")
- {
- _locale = new Intl.Locale("zh", { region: _locale.maximize().region });
- }
- ;
- if (_locale.baseName in translations)
- {
- locale = _locale.baseName;
- break;
- }
- }
-
- return i18nObject(locale, translations[locale]);
- })();
-
- const EVENT_KEY = uuid();
-
- const ExpandOptions =
- {
- EXPAND_ALL: "expand_all",
- LAST_READ: "last_read",
- };
-
- GM.registerMenuCommand(LL.COMMAND.SETTING(), showExpandSetting);
-
- (async () =>
- {
- const setting = await getExpandSetting();
-
- const elements = document.querySelectorAll("#chapterList details");
- for (const element of elements)
- {
- if ((setting === ExpandOptions.EXPAND_ALL) || (element.querySelector("p.active") !== null))
- {
- element.open = true;
- }
- }
- })();
-
- function getExpandSetting()
- {
- return GM.getValue("expand", ExpandOptions.LAST_READ);
- }
-
- let settingOpened = false;
-
- function showExpandSetting()
- {
- if (settingOpened) { return Promise.resolve(new Error("Setting was already opened.")); }
-
- return new Promise(async (resolve) =>
- {
- const setting = await getExpandSetting();
-
- const form = document.createElement("form");
- form.id = uuid();
- form.classList.add("modal", "fade");
- form.addEventListener("submit", async (event) =>
- {
- event.preventDefault();
-
- const settings = new FormData(form);
- await GM.setValue("expand", settings.get("expand"));
-
- window.dispatchEvent(new CustomEvent(`${EVENT_KEY}:hideModal`, { detail: `#${form.id}` }));
- });
- form.addEventListener("hide.bs.modal", () => resolve());
- form.addEventListener("hidden.bs.modal", () =>
- {
- form.remove();
- settingOpened = false;
- });
-
- const modalDialog = document.createElement("div");
- modalDialog.classList.add("modal-dialog");
-
- const modalContent = document.createElement("div");
- modalContent.classList.add("modal-content");
-
- const modalHeader = document.createElement("div");
- modalHeader.classList.add("modal-header");
-
- const modalTitle = document.createElement("h4");
- modalTitle.classList.add("modal-title");
- modalTitle.innerText = LL.SETTING.TITLE();
-
- const closeButton = document.createElement("button");
- closeButton.classList.add("close");
- closeButton.type = "button";
- closeButton.dataset.dismiss = "modal";
- closeButton.innerHTML = `<span aria-hidden="true">×</span>`;
-
- const modalBody = document.createElement("div");
- modalBody.classList.add("modal-body");
-
- const expandFormGroup = document.createElement("div");
- expandFormGroup.classList.add("form-group");
-
- const expandSelect = document.createElement("select");
- expandSelect.id = "expand-select";
- expandSelect.classList.add("form-control");
- expandSelect.name = "expand";
-
- const expandAllOption = document.createElement("option");
- expandAllOption.value = ExpandOptions.EXPAND_ALL;
- expandAllOption.selected = (setting === ExpandOptions.EXPAND_ALL);
- expandAllOption.innerText = LL.SETTING.EXPAND_ALL();
-
- const lastReadOption = document.createElement("option");
- lastReadOption.value = ExpandOptions.LAST_READ;
- lastReadOption.selected = (setting === ExpandOptions.LAST_READ);
- lastReadOption.innerText = LL.SETTING.LAST_READ();
-
- const modalFooter = document.createElement("div");
- modalFooter.classList.add("modal-footer");
-
- const cancelButton = document.createElement("button");
- cancelButton.classList.add("btn", "btn-default");
- cancelButton.type = "button";
- cancelButton.dataset.dismiss = "modal";
- cancelButton.innerText = LL.SETTING.CANCEL();
-
- const saveButton = document.createElement("button");
- saveButton.classList.add("btn", "btn-primary");
- cancelButton.type = "submit";
- saveButton.innerText = LL.SETTING.SAVE();
-
- modalHeader.append(modalTitle, closeButton);
- expandSelect.append(expandAllOption, lastReadOption);
- expandFormGroup.append(expandSelect);
- modalBody.append(expandFormGroup);
- modalFooter.append(cancelButton, saveButton);
- modalContent.append(modalHeader, modalBody, modalFooter);
- modalDialog.append(modalContent);
- form.append(modalDialog);
- document.body.append(form);
-
- window.dispatchEvent(new CustomEvent(`${EVENT_KEY}:showModal`, { detail: `#${form.id}` }));
- settingOpened = true;
- });
- }
-
- const PageScript = ({ EVENT_KEY }) =>
- {
- window.addEventListener(`${EVENT_KEY}:showModal`, ({ detail: selector }) =>
- {
- $(selector)
- .on("hide.bs.modal", (event) =>
- {
- event.target.dispatchEvent(new CustomEvent("hide.bs.modal", { ...event }));
- })
- .on("hidden.bs.modal", (event) =>
- {
- event.target.dispatchEvent(new CustomEvent("hidden.bs.modal", { ...event }));
- })
- .modal("show");
- });
-
- window.addEventListener(`${EVENT_KEY}:hideModal`, ({ detail: selector }) =>
- {
- $(selector)
- .modal("hide");
- });
- };
-
- const scriptWrapper = document.createElement("div");
- scriptWrapper.style.display = "none";
- const shadowRoot = scriptWrapper.attachShadow({ mode: "closed" });
- const script = document.createElement("script");
- script.textContent = `(${PageScript})(${JSON.stringify({ EVENT_KEY })}); //# sourceURL=userscript://page/${encodeURI(GM.info.script.name)}.js`;
- shadowRoot.append(script);
- (document.body ?? document.head ?? document.documentElement).append(scriptWrapper);