Github Image Viewer

Preview images from within the listing.

目前為 2018-09-27 提交的版本,檢視 最新版本

  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 (http://jeroenvanwarmerdam.nl)
  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.1
  15. // @icon https://assets-cdn.github.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://assets-cdn.github.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.borderBottom = "1px solid #d8e6ec";
  71. floaterTitle.style.padding = "3px 5px";
  72. floaterMouseAlign.appendChild(floaterTitle);
  73.  
  74. var floaterCenter = document.createElement("div");
  75. floaterCenter.style.minWidth = "40px";
  76. floaterCenter.style.minHeight = "40px";
  77. floaterCenter.style.display = "flex";
  78. floaterCenter.style.flexDirection = "column";
  79. floaterCenter.style.backgroundColor = "#f8f8f8";
  80. floaterCenter.style.padding = "3px";
  81. floaterMouseAlign.appendChild(floaterCenter);
  82.  
  83. var floaterImage = GithubImageViewer._floaterImage = document.createElement("img");
  84. floaterImage.setAttribute("src", GithubImageViewer._loaderSrc);
  85. floaterImage.style.margin = "auto";
  86. floaterImage.style.maxWidth = floaterImage.style.maxHeight = "200px";
  87. floaterCenter.appendChild(floaterImage);
  88.  
  89. var floaterMeta = GithubImageViewer._floaterMeta = document.createElement("div");
  90. floaterMeta.style.backgroundColor = "#f8f8f8";
  91. floaterMeta.style.padding = "3px";
  92. floaterMeta.style.textAlign = "center";
  93. floaterMeta.style.whiteSpace = "nowrap";
  94. floaterMouseAlign.appendChild(floaterMeta);
  95. GithubImageViewer.SetMeta();
  96.  
  97. GithubImageViewer.Attach();
  98. },
  99.  
  100. Attach: function() {
  101. document.getElementById("js-repo-pjax-container").addEventListener("mousemove", function(e) {
  102. var target = e.target;
  103. if (target.classList && target.classList.contains("js-navigation-open") &&
  104. GithubImageViewer._imageRegex.test(target.href)) {
  105.  
  106. if (target.getAttribute("title")) {
  107. target.dataset.title = target.getAttribute("title");
  108. target.removeAttribute("title");
  109. }
  110.  
  111. if (GithubImageViewer._visible) {
  112. GithubImageViewer.Show(e.pageX, e.pageY);
  113. } else {
  114. GithubImageViewer.AddTimer(proxy(function() {
  115. GithubImageViewer.ClearTimers();
  116.  
  117. GithubImageViewer.Show(e.pageX, e.pageY);
  118.  
  119. var href = target.href;
  120. if (GithubImageViewer._imageUrl !== href) {
  121. GithubImageViewer._imageUrl = href;
  122. GithubImageViewer.SetImage(GithubImageViewer._imageUrl);
  123.  
  124. GithubImageViewer.SetTitle(target.dataset.title);
  125. }
  126. }));
  127. }
  128. } else {
  129. GithubImageViewer.Dispose();
  130. }
  131. });
  132. document.body.addEventListener("click", function() {
  133. GithubImageViewer.Dispose();
  134. });
  135. document.body.addEventListener("contextmenu", function() {
  136. GithubImageViewer.Dispose();
  137. });
  138. document.body.addEventListener("keydown", function(e) {
  139. if (e.keyCode === 27) {
  140. GithubImageViewer.Dispose();
  141. }
  142. });
  143. },
  144.  
  145. _visible: false,
  146. Show: function(x, y) {
  147. GithubImageViewer._visible = true;
  148. GithubImageViewer._floater.style.left = x + "px";
  149. GithubImageViewer._floater.style.top = y + "px";
  150. },
  151. Hide: function() {
  152. GithubImageViewer._visible = false;
  153. GithubImageViewer._floater.style.left = "-1000px";
  154. GithubImageViewer._floater.style.top = "-1000px";
  155. },
  156.  
  157. Dispose: function() {
  158. GithubImageViewer.ClearTimers();
  159.  
  160. GithubImageViewer.Hide();
  161.  
  162. GithubImageViewer._imageUrl = GithubImageViewer._loaderSrc;
  163. GithubImageViewer.SetImage(GithubImageViewer._imageUrl);
  164.  
  165. GithubImageViewer.SetTitle("Loading...");
  166. },
  167.  
  168. _timers: [],
  169. _timeout: 700,
  170. AddTimer: function(fn) {
  171. GithubImageViewer._timers.push(window.setTimeout(fn, GithubImageViewer._timeout));
  172. },
  173. ClearTimers: function() {
  174. Array.prototype.forEach.call(GithubImageViewer._timers, function(timer) {
  175. window.clearTimeout(timer);
  176. });
  177. },
  178.  
  179. SetTitle: function(text) {
  180. GithubImageViewer._floaterTitle.textContent = text;
  181. },
  182.  
  183. SetImage: function(src) {
  184. src = src.replace("/blob/", "/raw/");
  185. if (src !== GithubImageViewer._loaderSrc) {
  186. var temp = document.createElement("img");
  187. temp.style.visibility = "hidden";
  188. temp.addEventListener("load", function() {
  189. GithubImageViewer.SetMeta(this.width, this.height);
  190. this.parentNode.removeChild(temp);
  191. });
  192. temp.setAttribute("src", src);
  193. document.body.appendChild(temp);
  194. } else {
  195. GithubImageViewer.SetMeta();
  196. }
  197.  
  198. GithubImageViewer._floaterImage.setAttribute("src", src);
  199. },
  200.  
  201. SetMeta: function(w, h) {
  202. if (!w && !h) {
  203. GithubImageViewer._floaterMeta.style.display = "none";
  204. } else {
  205. GithubImageViewer._floaterMeta.style.display = "block";
  206. GithubImageViewer._floaterMeta.innerHTML = String.format("<strong>W:</strong> {0}px | <strong>H:</strong> {1}px", w, h);
  207. }
  208. }
  209. };
  210.  
  211. if (document.getElementById("js-repo-pjax-container")) {
  212. GithubImageViewer.Initialize();
  213. }
  214.  
  215. })();