Github Image Viewer

Preview images from within the listing.

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