Edge Local File Enhancer

Enhance the experience of viewing local files on Edge.

目前为 2023-10-25 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Edge Local File Enhancer
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1.5
  5. // @description Enhance the experience of viewing local files on Edge.
  6. // @author PRO
  7. // @match file:///*/
  8. // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABt0lEQVR42oxStZoWQRCs2cXdHTLcHZ6EjAwnQWIkJyQlRt4Cd3d3d1n5d7q7ju1zv/q+mh6taQsk8fn29kPDRo87SDMQcNAUJgIQkBjdAoRKdXjm2mOH0AqS+PlkP8sfp0h93iu/PDji9s2FzSSJVg5ykZqWgfGRr9rAAAQiDFoB1OfyESZEB7iAI0lHwLREQBcQQKqo8p+gNUCguwCNAAUQAcFOb0NNGjT+BbUC2YsHZpWLhC6/m0chqIoM1LKbQIIBwlTQE1xAo9QDGDPYf6rkTpPc92gCUYVJAZjhyZltJ95f3zuvLYRGWWCUNkDL2333McBh4kaLlxg+aTmyL7c2xTjkN4Bt7oE3DBP/3SRz65R/bkmBRPGzcRNHYuzMjaj+fdnaFoJUEdTSXfaHbe7XNnMPyqryPcmfY+zURaAB7SHk9cXSH4fQ5rojgCAVIuqCNWgRhLYLhJB4k3iZfIPtnQiCpjAzeBIRXMA6emAqoEbQSoDdGxFUrxS1AYcpaNbBgyQBGJEOnYOeENKR/iAd1npusI4C75/c3539+nbUjOgZV5CkAU27df40lH+agUdIuA/EAgDmZnwZlhDc0wAAAABJRU5ErkJggg==
  9. // @grant none
  10. // @run-at document-end
  11. // @license gpl-3.0
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16. // Helper functions
  17. const path = location.href;
  18. if (!path.startsWith("file:///") || !path.endsWith("/")) return;
  19. const debug = false;
  20. const log = debug ? console.log.bind(console, "[ELFE]") : () => {};
  21. const $ = document.querySelector.bind(document);
  22. const $$ = document.querySelectorAll.bind(document);
  23. const getModifier = (e) => (e.ctrlKey << 2 | e.shiftKey << 1 | e.altKey);
  24. const hasModifier = (e, test = 0b111) => Boolean(getModifier(e) & test);
  25. const modifierDict = (e) => {
  26. return {
  27. "button": e.button || 0,
  28. "ctrlKey": e.ctrlKey,
  29. "shiftKey": e.shiftKey,
  30. "altKey": e.altKey,
  31. "bubble": false,
  32. }
  33. };
  34.  
  35. // CSS
  36. const header = $("h1#header");
  37. const css = document.createElement("style");
  38. css.id = "elfe-css";
  39. css.textContent = `
  40. html { scroll-behavior: smooth; }
  41. h1#header > a { color: initial; text-decoration: none; transition: color 0.2s ease-in-out; }
  42. h1#header > a:hover { color: -webkit-link; }
  43. table { margin: 0.5rem 0; width: auto; }
  44. table td, table th { padding: 0.3rem 0.5rem; vertical-align: middle; }
  45. div#parentDirLinkBox { display: none !important; }
  46. #parentDir { padding: 0 0.5em 0; }
  47. thead th { border-left: 1px solid gray; border-right: 1px solid gray; }
  48. thead th, tbody tr { transition: background-color 0.2s ease-in-out; cursor: pointer; }
  49. thead th:hover, tbody tr:hover { background-color: #333333; }
  50. tbody tr.selected { background-color: #4d4d4d; }
  51. `;
  52. $("head").appendChild(css);
  53.  
  54. // Navigation
  55. const delimeter = header.textContent.includes("\\") ? "\\" : "/";
  56. const split = header.textContent.split(delimeter);
  57. log(split);
  58. const parts = split.slice(0, -1);
  59. header.innerHTML = '<a href="../" id="parentDir">↑</a>'
  60. + parts.map((part, i) =>
  61. `<a href="${parts.slice(0, i + 1).join(delimeter)}${delimeter}">${part}</a>`
  62. ).join(delimeter) + delimeter + split.slice(-1)[0];
  63.  
  64. // Table
  65. const rows = $$("tbody tr");
  66. rows.forEach(row => {
  67. row.addEventListener("click", e => {
  68. if (e.button != 0) return true;
  69. log(e);
  70. e.preventDefault();
  71. row.querySelector("a").dispatchEvent(new MouseEvent("click", modifierDict(e)));
  72. return true;
  73. });
  74. });
  75. $$("td").forEach(td => {
  76. td.title = td.getAttribute("data-value") || td.textContent;
  77. });
  78.  
  79. // Shortcuts
  80. const parentDir = $("#parentDir");
  81. const count = rows.length;
  82. var selected = 0;
  83. function select(i) {
  84. rows[selected].classList.remove("selected");
  85. selected = i;
  86. rows[selected].classList.add("selected");
  87. rows[selected].scrollIntoView({ block: "center" });
  88. }
  89. function delta(d) {
  90. select((selected + d + count) % count);
  91. }
  92. document.addEventListener("keydown", e => {
  93. switch (e.key) {
  94. case "ArrowUp":
  95. e.preventDefault();
  96. if (e.altKey && parentDir) { // Go to parent directory
  97. parentDir.click();
  98. break;
  99. }
  100. if (e.ctrlKey) { // Scroll up
  101. window.scrollBy({ top: -window.innerHeight / 2});
  102. break;
  103. }
  104. if (count == 0) break;
  105. if (e.shiftKey) { // Select top
  106. select(0);
  107. break;
  108. }
  109. // Select previous
  110. delta(-1);
  111. break;
  112. case "ArrowDown":
  113. e.preventDefault();
  114. if (e.ctrlKey) { // Scroll down
  115. window.scrollBy({ top: window.innerHeight / 2});
  116. break;
  117. }
  118. if (count == 0) break;
  119. if (e.shiftKey) { // Select bottom
  120. select(count - 1);
  121. break;
  122. }
  123. // Select next
  124. delta(1);
  125. break;
  126. case "ArrowLeft":
  127. if (hasModifier(e)) break; // Try to be none-intrusive
  128. history.back(); break;
  129. case "ArrowRight":
  130. if (hasModifier(e)) break;
  131. history.forward(); break;
  132. case "Enter": {
  133. if (count == 0) break;
  134. e.preventDefault();
  135. const link = rows[selected].querySelector("a");
  136. link.dispatchEvent(new MouseEvent("click", modifierDict(e)));
  137. break;
  138. }
  139. default: break;
  140. }
  141. });
  142. })();