Github Image Viewer

Preview images from within the listing.

当前为 2022-12-16 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @id Github_Image_Viewer@https://github.com/jerone/UserScripts
  3. // @name Github Image Viewer
  4. // @namespace https://github.com/jerone/UserScripts
  5. // @description Preview images from within the listing.
  6. // @author jerone
  7. // @copyright 2014+, jerone (https://github.com/jerone)
  8. // @license CC-BY-NC-SA-4.0; https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
  9. // @license GPL-3.0-or-later; http://www.gnu.org/licenses/gpl-3.0.txt
  10. // @homepage https://github.com/jerone/UserScripts/tree/master/Github_Image_Viewer
  11. // @homepageURL https://github.com/jerone/UserScripts/tree/master/Github_Image_Viewer
  12. // @supportURL https://github.com/jerone/UserScripts/issues
  13. // @contributionURL https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=VCYMHWQ7ZMBKW
  14. // @version 0.4.2
  15. // @icon https://github.githubassets.com/pinned-octocat.svg
  16. // @grant none
  17. // @run-at document-end
  18. // @include https://github.com/*
  19. // ==/UserScript==
  20.  
  21. (function() {
  22.  
  23. String.format = function(string) {
  24. var args = Array.prototype.slice.call(arguments, 1, arguments.length);
  25. return string.replace(/{(\d+)}/g, function(match, number) {
  26. return typeof args[number] !== "undefined" ? args[number] : match;
  27. });
  28. };
  29.  
  30. function proxy(fn) {
  31. return function() {
  32. var that = this;
  33. return function(e) {
  34. var args = that.slice(0); // clone;
  35. args.unshift(e); // prepend event;
  36. fn.apply(this, args);
  37. };
  38. }.call([].slice.call(arguments, 1));
  39. }
  40.  
  41. var GithubImageViewer = {
  42. _floater: null,
  43. _floaterTitle: null,
  44. _floaterImage: null,
  45. _floaterMeta: null,
  46.  
  47. _imageUrl: null,
  48. _loaderSrc: "https://github.githubassets.com/images/spinners/octocat-spinner-32.gif",
  49. _imageRegex: /.+(\.jpe?g|\.png|\.gif|\.bmp|\.ico|\.tiff?)$/i,
  50.  
  51. Initialize: function() {
  52. var floater = GithubImageViewer._floater = document.createElement("div");
  53. floater.style.position = "absolute";
  54. floater.style.top = "0";
  55. floater.style.left = "0";
  56. floater.style.zIndex = "999";
  57. document.body.appendChild(floater);
  58.  
  59. var floaterMouseAlign = document.createElement("div");
  60. floaterMouseAlign.style.position = "absolute";
  61. floaterMouseAlign.style.bottom = "5px";
  62. floaterMouseAlign.style.left = "5px";
  63. floaterMouseAlign.style.border = "1px solid #b7c7cf";
  64. floaterMouseAlign.style.borderRadius = "3px";
  65. floaterMouseAlign.style.fontSize = "11px";
  66. floater.appendChild(floaterMouseAlign);
  67.  
  68. var floaterTitle = GithubImageViewer._floaterTitle = document.createElement("div");
  69. floaterTitle.style.backgroundColor = "#e6f1f6";
  70. floaterTitle.style.color = "black";
  71. floaterTitle.style.textAlign = "center";
  72. floaterTitle.style.borderBottom = "1px solid #d8e6ec";
  73. floaterTitle.style.padding = "3px 5px";
  74. floaterMouseAlign.appendChild(floaterTitle);
  75.  
  76. var floaterCenter = document.createElement("div");
  77. floaterCenter.style.minWidth = "40px";
  78. floaterCenter.style.minHeight = "40px";
  79. floaterCenter.style.display = "flex";
  80. floaterCenter.style.flexDirection = "column";
  81. floaterCenter.style.backgroundColor = "#f8f8f8";
  82. floaterCenter.style.padding = "3px";
  83. floaterMouseAlign.appendChild(floaterCenter);
  84.  
  85. var floaterImage = GithubImageViewer._floaterImage = document.createElement("img");
  86. floaterImage.setAttribute("src", GithubImageViewer._loaderSrc);
  87. floaterImage.style.margin = "auto";
  88. floaterImage.style.maxWidth = floaterImage.style.maxHeight = "200px";
  89. floaterCenter.appendChild(floaterImage);
  90.  
  91. var floaterMeta = GithubImageViewer._floaterMeta = document.createElement("div");
  92. floaterMeta.style.backgroundColor = "#f8f8f8";
  93. floaterMeta.style.color = "black";
  94. floaterMeta.style.padding = "3px";
  95. floaterMeta.style.textAlign = "center";
  96. floaterMeta.style.whiteSpace = "nowrap";
  97. floaterMouseAlign.appendChild(floaterMeta);
  98. GithubImageViewer.SetMeta();
  99.  
  100. GithubImageViewer.Attach();
  101. },
  102.  
  103. Attach: function() {
  104. document.getElementById("js-repo-pjax-container").addEventListener("mousemove", function(e) {
  105. var target = e.target;
  106. if (target.classList && target.classList.contains("js-navigation-open") &&
  107. GithubImageViewer._imageRegex.test(target.href)) {
  108.  
  109. if (target.getAttribute("title")) {
  110. target.dataset.title = target.getAttribute("title");
  111. target.removeAttribute("title");
  112. }
  113.  
  114. if (GithubImageViewer._visible) {
  115. GithubImageViewer.Show(e.pageX, e.pageY);
  116. } else {
  117. GithubImageViewer.AddTimer(proxy(function() {
  118. GithubImageViewer.ClearTimers();
  119.  
  120. GithubImageViewer.Show(e.pageX, e.pageY);
  121.  
  122. var href = target.href;
  123. if (GithubImageViewer._imageUrl !== href) {
  124. GithubImageViewer._imageUrl = href;
  125. GithubImageViewer.SetImage(GithubImageViewer._imageUrl);
  126.  
  127. GithubImageViewer.SetTitle(target.dataset.title);
  128. }
  129. }));
  130. }
  131. } else {
  132. GithubImageViewer.Dispose();
  133. }
  134. });
  135. document.body.addEventListener("click", function() {
  136. GithubImageViewer.Dispose();
  137. });
  138. document.body.addEventListener("contextmenu", function() {
  139. GithubImageViewer.Dispose();
  140. });
  141. document.body.addEventListener("keydown", function(e) {
  142. if (e.keyCode === 27) {
  143. GithubImageViewer.Dispose();
  144. }
  145. });
  146. },
  147.  
  148. _visible: false,
  149. Show: function(x, y) {
  150. GithubImageViewer._visible = true;
  151. GithubImageViewer._floater.style.left = x + "px";
  152. GithubImageViewer._floater.style.top = y + "px";
  153. },
  154. Hide: function() {
  155. GithubImageViewer._visible = false;
  156. GithubImageViewer._floater.style.left = "-1000px";
  157. GithubImageViewer._floater.style.top = "-1000px";
  158. },
  159.  
  160. Dispose: function() {
  161. GithubImageViewer.ClearTimers();
  162.  
  163. GithubImageViewer.Hide();
  164.  
  165. GithubImageViewer._imageUrl = GithubImageViewer._loaderSrc;
  166. GithubImageViewer.SetImage(GithubImageViewer._imageUrl);
  167.  
  168. GithubImageViewer.SetTitle("Loading...");
  169. },
  170.  
  171. _timers: [],
  172. _timeout: 700,
  173. AddTimer: function(fn) {
  174. GithubImageViewer._timers.push(window.setTimeout(fn, GithubImageViewer._timeout));
  175. },
  176. ClearTimers: function() {
  177. Array.prototype.forEach.call(GithubImageViewer._timers, function(timer) {
  178. window.clearTimeout(timer);
  179. });
  180. },
  181.  
  182. SetTitle: function(text) {
  183. GithubImageViewer._floaterTitle.textContent = text;
  184. },
  185.  
  186. SetImage: function(src) {
  187. src = src.replace("/blob/", "/raw/");
  188. if (src !== GithubImageViewer._loaderSrc) {
  189. var temp = document.createElement("img");
  190. temp.style.visibility = "hidden";
  191. temp.addEventListener("load", function() {
  192. GithubImageViewer.SetMeta(this.width, this.height);
  193. this.parentNode.removeChild(temp);
  194. });
  195. temp.setAttribute("src", src);
  196. document.body.appendChild(temp);
  197. } else {
  198. GithubImageViewer.SetMeta();
  199. }
  200.  
  201. GithubImageViewer._floaterImage.setAttribute("src", src);
  202. },
  203.  
  204. SetMeta: function(w, h) {
  205. if (!w && !h) {
  206. GithubImageViewer._floaterMeta.style.display = "none";
  207. } else {
  208. GithubImageViewer._floaterMeta.style.display = "block";
  209. GithubImageViewer._floaterMeta.innerHTML = String.format("<strong>W:</strong> {0}px | <strong>H:</strong> {1}px", w, h);
  210. }
  211. }
  212. };
  213.  
  214. if (document.getElementById("js-repo-pjax-container")) {
  215. GithubImageViewer.Initialize();
  216. }
  217.  
  218. })();