- // ==UserScript==
- // @name 学习通/MOOC等 隐藏答案 Hide Answer
- // @namespace https://github.com/lcandy2/user.js/tree/main/generics/hide-answer
- // @version 2.3.2
- // @author 甜檸Cirtron (lcandy2)
- // @description 添加一个切换答案按钮,点击可显示/隐藏答案
- // @license AGPL-3.0-or-later
- // @copyright lcandy2 All Rights Reserved
- // @homepage https://gf.qytechs.cn/scripts/469779
- // @homepageURL https://gf.qytechs.cn/scripts/469779
- // @match *://mooc1.chaoxing.com/mooc*
- // @match *://mooc1.chaoxing.com/exam*
- // @require https://registry.npmmirror.com/vue/3.4.27/files/dist/vue.global.prod.js
- // @require data:application/javascript,%3Bwindow.Vue%3DVue%3B
- // ==/UserScript==
-
- (function (vue) {
- 'use strict';
-
- const chaoxingMooc = "mooc1.chaoxing.com/mooc";
- const chaoxingExam = "mooc1.chaoxing.com/exam";
- const UrlDetection = () => {
- const url = window.location.href;
- if (url.includes(chaoxingMooc) || url.includes(chaoxingExam)) {
- if (url.includes("work/view") || url.includes("test/reVersionPaperMarkContentNew")) {
- return "chaoxing-mooc";
- }
- }
- };
- var oe = "M8.27,3L3,8.27V15.73L8.27,21H15.73C17.5,19.24 21,15.73 21,15.73V8.27L15.73,3M9.1,5H14.9L19,9.1V14.9L14.9,19H9.1L5,14.9V9.1M11,15H13V17H11V15M11,7H13V13H11V7", ae = "M12,2L1,21H23M12,6L19.53,19H4.47M11,10V14H13V10M11,16V18H13V16", re = "M12 2C6.5 2 2 6.5 2 12S6.5 22 12 22 22 17.5 22 12 17.5 2 12 2M10 17L5 12L6.41 10.59L10 14.17L17.59 6.58L19 8L10 17Z", ne = "M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z", ie = "M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M11,17H13V11H11V17Z";
- const le = {
- transform: "rotate(var(--r, 0deg)) scale(var(--sx, 1), var(--sy, 1))"
- }, E = {
- fill: "currentColor"
- }, z = {
- mdi: {
- size: 24,
- viewbox: "0 0 24 24"
- },
- "simple-icons": {
- size: 24,
- viewbox: "0 0 24 24"
- },
- default: {
- size: 0,
- viewbox: "0 0 0 0"
- }
- }, N = {
- name: "icon",
- props: {
- type: {
- type: String,
- default: "mdi"
- },
- faIcon: {
- type: Object,
- default: null
- },
- path: {
- type: [String, Object, Array]
- },
- size: {
- type: [Number, String],
- default: 24
- },
- viewbox: String,
- flip: {
- type: String,
- validator: (t) => ["horizontal", "vertical", "both"].includes(t)
- },
- rotate: {
- type: [Number, String],
- default: 0
- }
- },
- setup(t) {
- if (!t.path && !t.faIcon)
- return console.warn("vue3-icon requires either a 'path' or an 'fa-icon' property"), () => vue.h("div");
- const s = vue.computed(() => {
- var d;
- return ((d = t.faIcon) == null ? void 0 : d.prefix) || t.type;
- }), o = vue.computed(() => parseInt(t.rotate, 10)), e = vue.computed(() => z[s.value] || z.default), r = vue.computed(() => parseInt(t.size, 10) || e.value.size), i = vue.computed(() => t.faIcon ? `0 0 ${t.faIcon.icon[0]} ${t.faIcon.icon[1]}` : false), l = vue.computed(() => i.value || t.viewbox || e.value.viewbox), f = vue.computed(() => ({
- ...le,
- "--sx": ["both", "horizontal"].includes(t.flip) ? "-1" : "1",
- "--sy": ["both", "vertical"].includes(t.flip) ? "-1" : "1",
- "--r": isNaN(o.value) ? o.value : o.value + "deg"
- })), m = vue.computed(() => {
- var d;
- return t.faIcon ? (d = t.faIcon) == null ? void 0 : d.icon[4] : t.type === "simple-icons" && typeof t.path == "object" ? t.path.path : t.path;
- }), p = vue.computed(() => s.value === "fad" ? (console.warn("vue3-icon does not currently support Duotone FontAwesome icons"), vue.h("path")) : Array.isArray(t.path) ? vue.h(
- "g",
- { style: { ...E } },
- t.path.map((d) => typeof d == "string" ? vue.h("path", { d }) : vue.h("path", { ...d }))
- ) : vue.h("path", { d: m.value, style: { ...E } }));
- return () => vue.h(
- "svg",
- {
- style: f.value,
- class: ["vue3-icon"],
- width: r.value,
- height: r.value,
- viewBox: l.value
- },
- [p.value]
- );
- }
- }, ue = { class: "vue3-snackbar-message-wrapper" }, ce = {
- key: 0,
- class: "vue3-snackbar-message-icon"
- }, de = { class: "vue3-snackbar-message-content" }, fe = {
- key: 0,
- class: "vue3-snackbar-message-badge"
- }, me = { class: "vue3-snackbar-message-title" }, pe = {
- key: 0,
- class: "vue3-snackbar-message-additional"
- }, ge = /* @__PURE__ */ vue.createElementVNode("div", { class: "spacer" }, null, -1), ve = { class: "vue3-snackbar-message-close" }, be = {
- __name: "Vue3SnackbarMessage",
- props: {
- borderClass: {
- type: String,
- default: ""
- },
- message: {
- type: Object,
- default: () => ({})
- },
- messageClass: {
- type: String,
- default: ""
- },
- dense: {
- type: Boolean,
- default: false
- }
- },
- emits: ["dismiss"],
- setup(t, { emit: s }) {
- const o = s, e = t;
- let r = null, i = null, l = vue.ref(false);
- const f = () => {
- const a = !e.message.duration && !e.message.dismissible ? 4e3 : e.message.duration;
- r = setTimeout(p, a);
- };
- vue.onMounted(() => {
- f();
- }), vue.watch(
- () => e.message.count,
- (a) => {
- if (a === 1)
- return false;
- clearTimeout(r), clearTimeout(i), i = setTimeout(() => {
- l.value = false;
- }, 1e3), l.value = true, f();
- }
- );
- const m = () => {
- r && clearTimeout(r), p();
- }, p = () => {
- o("dismiss", e.message);
- }, d = {
- success: {
- path: re
- },
- info: {
- path: ie
- },
- warning: {
- path: ae
- },
- error: {
- path: oe
- }
- }, n = vue.computed(() => {
- const a = d[e.message.type];
- return a ? (a.type = "mdi", a) : e.message.icon && typeof e.message.icon == "object" ? e.message.icon : {
- path: "",
- type: "default"
- };
- });
- return (a, u) => (vue.openBlock(), vue.createElementBlock("article", {
- class: vue.normalizeClass(["vue3-snackbar-message", [
- e.message.type || "custom",
- e.messageClass,
- e.borderClass,
- {
- "has-background": e.message.background,
- "has-border": e.borderClass,
- "is-dense": e.dense,
- "shake-baby-shake": vue.unref(l)
- }
- ]]),
- style: vue.normalizeStyle({
- "--message-background": e.message.background,
- "--message-text-color": e.message.textColor,
- "--message-icon-color": e.message.iconColor
- })
- }, [
- vue.renderSlot(a.$slots, "message-inner", {
- message: e.message
- }, () => [
- vue.createElementVNode("div", ue, [
- n.value ? (vue.openBlock(), vue.createElementBlock("div", ce, [
- vue.renderSlot(a.$slots, "message-icon", {
- message: e.message,
- icon: n.value
- }, () => [
- vue.createVNode(vue.unref(N), vue.mergeProps(n.value, { role: "img" }), null, 16)
- ])
- ])) : vue.createCommentVNode("", true),
- vue.createElementVNode("div", de, [
- vue.renderSlot(a.$slots, "message-badge", {
- message: e.message,
- count: e.message.count
- }, () => [
- e.message.count > 1 ? (vue.openBlock(), vue.createElementBlock("div", fe, vue.toDisplayString(e.message.count), 1)) : vue.createCommentVNode("", true)
- ]),
- vue.renderSlot(a.$slots, "message-content", {
- message: e.message,
- title: e.message.title,
- text: e.message.text
- }, () => [
- vue.createElementVNode("div", me, vue.toDisplayString(e.message.title || e.message.text), 1),
- e.message.title && e.message.text ? (vue.openBlock(), vue.createElementBlock("div", pe, vue.toDisplayString(e.message.text), 1)) : vue.createCommentVNode("", true)
- ])
- ]),
- ge,
- vue.createElementVNode("div", ve, [
- vue.renderSlot(a.$slots, "message-close-icon", {
- message: e.message,
- isDimissible: e.message.dismissible,
- isDismissible: e.message.dismissible,
- dismiss: m
- }, () => [
- e.message.dismissible !== false ? (vue.openBlock(), vue.createElementBlock("button", {
- key: 0,
- onClick: m
- }, [
- vue.createVNode(vue.unref(N), {
- type: "mdi",
- path: vue.unref(ne)
- }, null, 8, ["path"])
- ])) : vue.createCommentVNode("", true)
- ])
- ])
- ])
- ])
- ], 6));
- }
- }, ye = typeof window < "u" ? HTMLElement : Object, he = {
- /* ******************************************
- * LOCATION PROPS
- ****************************************** */
- top: {
- type: Boolean,
- default: false
- },
- bottom: {
- type: Boolean,
- default: false
- },
- left: {
- type: Boolean,
- default: false
- },
- right: {
- type: Boolean,
- default: false
- },
- /* ******************************************
- * COLOUR PROPS
- ****************************************** */
- success: {
- type: String,
- default: "#4caf50"
- },
- error: {
- type: String,
- default: "#ff5252"
- },
- warning: {
- type: String,
- default: "#fb8c00"
- },
- info: {
- type: String,
- default: "#2196f3"
- },
- messageTextColor: {
- type: String,
- default: "#fff"
- },
- messageIconColor: {
- type: String,
- default: "currentColor"
- },
- /* ******************************************
- * OTHER PROPS
- ****************************************** */
- attach: {
- type: [String, ye],
- default: "body"
- },
- border: {
- type: String,
- default: "",
- validator: (t) => ["top", "bottom", "left", "right", ""].includes(t)
- },
- backgroundOpacity: {
- type: [String, Number],
- default: 0.12,
- validator: (t) => !isNaN(parseFloat(t)) && isFinite(t)
- },
- backgroundColor: {
- type: String,
- default: "currentColor"
- },
- baseBackgroundColor: {
- type: String,
- default: "#fff"
- },
- duration: {
- type: [Number, String],
- default: null
- },
- messageClass: {
- type: String
- },
- zIndex: {
- type: Number,
- default: 1e4
- },
- dense: {
- type: Boolean,
- default: false
- },
- reverse: {
- type: Boolean,
- default: false
- },
- groups: {
- type: Boolean,
- default: false
- },
- shadow: {
- type: Boolean,
- default: false
- }
- };
- function Se(t) {
- return t && t.__esModule && Object.prototype.hasOwnProperty.call(t, "default") ? t.default : t;
- }
- var V = { exports: {} };
- function B() {
- }
- B.prototype = {
- on: function(t, s, o) {
- var e = this.e || (this.e = {});
- return (e[t] || (e[t] = [])).push({
- fn: s,
- ctx: o
- }), this;
- },
- once: function(t, s, o) {
- var e = this;
- function r() {
- e.off(t, r), s.apply(o, arguments);
- }
- return r._ = s, this.on(t, r, o);
- },
- emit: function(t) {
- var s = [].slice.call(arguments, 1), o = ((this.e || (this.e = {}))[t] || []).slice(), e = 0, r = o.length;
- for (e; e < r; e++)
- o[e].fn.apply(o[e].ctx, s);
- return this;
- },
- off: function(t, s) {
- var o = this.e || (this.e = {}), e = o[t], r = [];
- if (e && s)
- for (var i = 0, l = e.length; i < l; i++)
- e[i].fn !== s && e[i].fn._ !== s && r.push(e[i]);
- return r.length ? o[t] = r : delete o[t], this;
- }
- };
- V.exports = B;
- V.exports.TinyEmitter = B;
- var ke = V.exports, Ce = ke, we = new Ce();
- const _ = /* @__PURE__ */ Se(we), C = {
- $on: (...t) => _.on(...t),
- $once: (...t) => _.once(...t),
- $off: (...t) => _.off(...t),
- $emit: (...t) => _.emit(...t)
- }, b = vue.ref([]), W = Symbol();
- function Ee() {
- const t = vue.inject(W);
- if (!t)
- throw new Error("No Snackbar provided!");
- return t;
- }
- const ze = {
- install: (t, s = {}) => {
- const { disableGlobals: o = false } = s, e = {
- add: (r) => {
- C.$emit("add", r);
- },
- clear: () => {
- C.$emit("clear");
- }
- };
- o !== true && (t.config.globalProperties.$snackbar = e, typeof window < "u" && (window.$snackbar = e)), t.provide(W, e);
- }
- };
- function _e(t) {
- return vue.getCurrentScope() ? (vue.onScopeDispose(t), true) : false;
- }
- function P(t) {
- return typeof t == "function" ? t() : vue.unref(t);
- }
- const Z = typeof window < "u" && typeof document < "u";
- typeof WorkerGlobalScope < "u" && globalThis instanceof WorkerGlobalScope;
- const Me = (t) => t != null;
- function Le(t) {
- return vue.getCurrentInstance();
- }
- function $e(t, s = true, o) {
- Le() ? vue.onMounted(t, o) : s ? t() : vue.nextTick(t);
- }
- function xe(t) {
- var s;
- const o = P(t);
- return (s = o == null ? void 0 : o.$el) != null ? s : o;
- }
- const Ve = Z ? window : void 0, Be = Z ? window.document : void 0;
- function Oe() {
- const t = vue.ref(false), s = vue.getCurrentInstance();
- return s && vue.onMounted(() => {
- t.value = true;
- }, s), t;
- }
- function Te(t) {
- const s = Oe();
- return vue.computed(() => (s.value, !!t()));
- }
- function Ae(t, s, o = {}) {
- const { window: e = Ve, ...r } = o;
- let i;
- const l = Te(() => e && "MutationObserver" in e), f = () => {
- i && (i.disconnect(), i = void 0);
- }, m = vue.computed(() => {
- const a = P(t), u = (Array.isArray(a) ? a : [a]).map(xe).filter(Me);
- return new Set(u);
- }), p = vue.watch(
- () => m.value,
- (a) => {
- f(), l.value && a.size && (i = new MutationObserver(s), a.forEach((u) => i.observe(u, r)));
- },
- { immediate: true, flush: "post" }
- ), d = () => i == null ? void 0 : i.takeRecords(), n = () => {
- f(), p();
- };
- return _e(n), {
- isSupported: l,
- stop: n,
- takeRecords: d
- };
- }
- function He(t = {}) {
- const {
- document: s = Be,
- selector: o = "html",
- observe: e = false,
- initialValue: r = "ltr"
- } = t;
- function i() {
- var f, m;
- return (m = (f = s == null ? void 0 : s.querySelector(o)) == null ? void 0 : f.getAttribute("dir")) != null ? m : r;
- }
- const l = vue.ref(i());
- return $e(() => l.value = i()), e && s && Ae(
- s.querySelector(o),
- () => l.value = i(),
- { attributes: true }
- ), vue.computed({
- get() {
- return l.value;
- },
- set(f) {
- var m, p;
- l.value = f, s && (l.value ? (m = s.querySelector(o)) == null || m.setAttribute("dir", l.value) : (p = s.querySelector(o)) == null || p.removeAttribute("dir"));
- }
- });
- }
- const Ne = {
- __name: "Vue3Snackbar",
- props: { ...he },
- emits: ["added", "dismissed", "removed", "cleared"],
- setup(t, { emit: s }) {
- const o = He(), e = t, r = s, i = vue.computed(() => ({
- "is-top": e.top,
- "is-bottom": e.top === false && e.bottom,
- "is-left": e.left,
- "is-right": e.left === false && e.right,
- "is-middle": e.top === false && e.bottom === false,
- "is-centre": e.left === false && e.right === false,
- "has-shadow": e.shadow,
- "is-rtl": o.value === "rtl"
- })), l = vue.computed(() => ({
- "--success-colour": e.success,
- "--error-colour": e.error,
- "--warning-colour": e.warning,
- "--info-colour": e.info,
- "--snackbar-zindex": e.zIndex,
- "--background-opacity": e.backgroundOpacity,
- "--background-color": e.backgroundColor,
- "--base-background-color": e.baseBackgroundColor,
- "--message-text-color": e.messageTextColor,
- "--message-icon-color": e.messageIconColor
- })), f = vue.computed(() => e.border ? `border-${e.border}` : ""), m = (n) => Math.abs(n.split("").reduce((a, u) => (a << 5) - a + u.charCodeAt(0) | 0, 0));
- let p = 1;
- C.$on("add", (n) => {
- r("added", n), n.group || (n.group = m(`${n.type}${n.title}${n.text}`).toString(16)), e.duration && !n.duration && n.duration !== 0 && (n.duration = +e.duration);
- const a = n.group && b.value.find((u) => u.group === n.group);
- if (e.groups === false || !a) {
- const u = {
- ...n,
- id: p,
- count: 1
- };
- e.reverse ? b.value.unshift(u) : b.value.push(u), p++;
- } else
- a.count++;
- }), C.$on("clear", () => {
- r("cleared"), b.value = [];
- }), vue.onUnmounted(() => {
- C.$off("add"), C.$off("clear");
- });
- const d = (n, a = false) => {
- r(a ? "dismissed" : "removed", n), b.value = b.value.filter((u) => u.id !== n.id);
- };
- return (n, a) => (vue.openBlock(), vue.createBlock(vue.Teleport, {
- to: e.attach
- }, [
- vue.createElementVNode("section", {
- id: "vue3-snackbar--container",
- class: vue.normalizeClass([[i.value], "vue3-snackbar"]),
- style: vue.normalizeStyle(l.value)
- }, [
- vue.createVNode(vue.TransitionGroup, {
- name: "vue3-snackbar-message",
- tag: "div"
- }, {
- default: vue.withCtx(() => [
- (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(b), (u) => (vue.openBlock(), vue.createBlock(be, {
- key: u.id,
- message: u,
- "message-class": e.messageClass,
- dense: e.dense,
- "border-class": f.value,
- onDismiss: a[0] || (a[0] = (O) => d(O, true))
- }, vue.createSlots({ _: 2 }, [
- vue.renderList(n.$slots, (O, T) => ({
- name: T,
- fn: vue.withCtx((R) => [
- vue.renderSlot(n.$slots, T, vue.mergeProps({ ref_for: true }, R))
- ])
- }))
- ]), 1032, ["message", "message-class", "dense", "border-class"]))), 128))
- ]),
- _: 3
- })
- ], 6)
- ], 8, ["to"]));
- }
- };
- const _sfc_main = /* @__PURE__ */ vue.defineComponent({
- __name: "chaoxing-mooc",
- setup(__props) {
- const snackbar = Ee();
- const elements = Array.from(
- document.getElementsByClassName("mark_answer")
- );
- const isHide = vue.ref(false);
- const toggleHide = () => {
- const value = isHide.value;
- snackbar.clear();
- snackbar.add({
- type: value ? "info" : "success",
- title: value ? "答案已显示" : "答案已隐藏",
- text: '你还可以按下 "H" 键来切换答案的显示状态。'
- });
- elements.forEach((element) => {
- element.style.visibility = isHide.value ? "visible" : "hidden";
- });
- isHide.value = !isHide.value;
- };
- const keydownHandler = (event) => {
- if (event.key === "h" || event.key === "H") {
- toggleHide();
- }
- };
- vue.onMounted(() => {
- window.addEventListener("keydown", keydownHandler);
- });
- vue.onUnmounted(() => {
- window.removeEventListener("keydown", keydownHandler);
- });
- return (_ctx, _cache) => {
- return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [
- vue.createElementVNode("a", {
- href: "javascript:;",
- onClick: toggleHide,
- class: "fl",
- tabindex: "0",
- role: "button"
- }, vue.toDisplayString(isHide.value ? "显示答案 (H)" : "隐藏答案 (H)"), 1),
- vue.createVNode(vue.unref(Ne), {
- top: "",
- duration: 0,
- border: "left",
- shadow: "",
- dense: "",
- reverse: ""
- })
- ], 64);
- };
- }
- });
- const appendChaoxingMoocButton = () => {
- const app = vue.createApp(_sfc_main);
- app.use(ze);
- const targetElement = document.querySelector(".subNav");
- if (targetElement) {
- const css = document.createElement("link");
- css.rel = "stylesheet";
- css.href = "https://unpkg.zhimg.com/vue3-snackbar@2.2.2/dist/style.css";
- document.head.appendChild(css);
- const toggleButton = document.createElement("div");
- toggleButton.className = "sub-button fr";
- toggleButton.id = "submitFocus";
- toggleButton.setAttribute("tabIndex", "-1");
- targetElement.appendChild(toggleButton);
- app.mount(toggleButton);
- }
- };
- const urlDetection = UrlDetection();
- if (urlDetection === "chaoxing-mooc") {
- appendChaoxingMoocButton();
- }
-
- })(Vue);