AuthorTodayImprover

The script allows you to select text and use the context menu when reading a book.

当前为 2023-02-28 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name AuthorTodayImprover
  3. // @name:ru AuthorTodayImprover
  4. // @namespace 90h.yy.zz
  5. // @version 0.1.1
  6. // @author Ox90
  7. // @include https://author.today/reader/*
  8. // @description The script allows you to select text and use the context menu when reading a book.
  9. // @description:ru Скрипт возвращает возможность выделять текст и использовать контекстное меню при чтении на сайте.
  10. // @run-at document-start
  11. // @license MIT
  12. // ==/UserScript==
  13.  
  14. (function start() {
  15. "use strict";
  16.  
  17. /**
  18. * Старт скрипта. Вызывается после загрузки DOM-дерева.
  19. *
  20. * @return void
  21. */
  22. function start() {
  23. [ "#reader.page-content", "div.text-wrapper" ].forEach(function(selector) {
  24. const el = document.querySelector(selector);
  25. el && processElement(el);
  26. });
  27. }
  28.  
  29. /**
  30. * Обрабатывает переданный DOM-элемент.
  31. * Если у элемента нет класса loading, то он обрабатывается немедленно,
  32. * в ином случае на него вешается наблюдатель, а обратотка откладывается.
  33. *
  34. * @param Element el Обрабатываемый DOM-элемент
  35. *
  36. * @return void
  37. */
  38. function processElement(el) {
  39. if (!el.classList.contains("loading")) {
  40. fixStyles(removeEvents(el));
  41. return;
  42. }
  43. (new MutationObserver(function(mutations, observer) {
  44. observer.disconnect();
  45. processElement(el);
  46. })).observe(el, { attributes: true, attributeFilter: [ "class" ] });
  47. }
  48.  
  49. /**
  50. * Подменяет переданный элемент новым, который создается через перенос его детей переднанного элемента в новый
  51. * и копирование атрибутов из старого элемента в новый за исключением некоторых атрибутов, которые
  52. * блокируют привычную функциональность как выделение текста и контекстное меню.
  53. * el.cloneNode(true) здесь не используется, чтобы избежать потери обработчиков у вложенных элементов.
  54. *
  55. * @param Element el DOM-элемент для замены
  56. *
  57. * @return Element Вновь созданный элемент
  58. */
  59. function removeEvents(el) {
  60. const evil_attributes = [
  61. "oncontextmenu", "onmousedown", "onselectstart", "unselectable"
  62. ];
  63.  
  64. const new_el = document.createElement(el.tagName);
  65. for (let attr of el.attributes) {
  66. if (!evil_attributes.includes(attr.name)) {
  67. new_el.setAttribute(attr.name, attr.value);
  68. }
  69. }
  70. while (el.childNodes[0]) {
  71. new_el.appendChild(el.childNodes[0]);
  72. }
  73. el.replaceWith(new_el);
  74. return new_el;
  75. }
  76.  
  77. /**
  78. * Исправляет стили элемента таким образом, чтобы они не блокировали привычную для пользователя функциональность.
  79. *
  80. * @param Element el DOM-элемент для исравления
  81. *
  82. * @return void
  83. */
  84. function fixStyles(el) {
  85. el.classList.remove("noselect");
  86. el.style.userSelect = "text";
  87. }
  88.  
  89. //----------
  90.  
  91. if (document.readyState === "loading")
  92. window.addEventListener("DOMContentLoaded", start);
  93. else
  94. start();
  95.  
  96. }());
  97.  

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址