Pixiv Direct Links

Turns thumbnail titles into direct or mode=manga links, adds direct image links on mode=manga pages, replaces the medium thumbnail on mode=medium pages with the full size, and disables lazy-loading images.

当前为 2015-06-27 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Pixiv Direct Links
  3. // @namespace https://greasyfork.org/scripts/4555
  4. // @description Turns thumbnail titles into direct or mode=manga links, adds direct image links on mode=manga pages, replaces the medium thumbnail on mode=medium pages with the full size, and disables lazy-loading images.
  5. // @include http://www.pixiv.net*
  6. // @grant none
  7. // @version 2015.06.27
  8. // ==/UserScript==
  9.  
  10. //Turn thumbnail titles into direct links (single images) or mode=manga links. Some kinds of thumbnails aren't covered, and an isolated few (like #17099702) don't work.
  11. var directTitles = false;
  12.  
  13. //Append direct links below images on mode=manga pages
  14. var directManga = true;
  15.  
  16. //Replace the medium thumbnail on mode=medium pages with the full size. The image will be relinked to the full size regardless of this setting.
  17. var fullSizeMedium = true;
  18.  
  19. //Disable lazy loading images. These appear on mode=manga pages, rankings, and the "Recommended" section of the bookmarks page.
  20. var dontSayLazy = true;
  21.  
  22. //----------------------------------------------------------------//
  23.  
  24. var fullSizeWidth = "740px";
  25.  
  26. if( typeof(custom) != "undefined" )
  27. custom();
  28.  
  29. if( location.search.indexOf("mode=manga_big") > 0 || location.search.indexOf("mode=big") > 0 )
  30. {
  31. //Make the 'big'/'manga_big' image link to itself instead of closing the window
  32. var image = document.getElementsByTagName("img")[0];
  33. if( image )
  34. {
  35. var link = document.createElement("a");
  36. link.href = image.src;
  37. link.appendChild( document.createElement("img") ).src = image.src;
  38. document.body.innerHTML = "";
  39. document.body.appendChild( link );
  40. }
  41. }
  42. else if( location.search.indexOf("mode=manga") > 0 )
  43. {
  44. var container = document.getElementsByClassName("full-size-container");
  45. if( directManga && container.length )
  46. {
  47. //Check the mode=manga_big page for the first page to determine if the "_big_p" size exists.
  48. var req = new XMLHttpRequest();
  49. req.open( "GET", location.href.replace(/page=\d+&?/,'').replace('mode=manga','mode=manga_big&page=0'), true );
  50. req.onload = function()
  51. {
  52. var firstImage = req.responseXML.querySelector("img[src*='_p0.']").src;
  53. for( var i = 0; i < container.length; i++ )
  54. {
  55. //Add direct link below each page
  56. var link = document.createElement("a");
  57. link.textContent = "direct link";
  58. link.style.display = "block";
  59. link.href = firstImage.replace( "_p0.", "_p"+i+"." );
  60. container[i].parentNode.appendChild( link );
  61. }
  62. };
  63. req.responseType = "document";
  64. req.send(null);
  65. }
  66. }
  67. else if( window == window.top )//not inside iframe
  68. {
  69. if( directTitles )
  70. {
  71. //Link dem titles.
  72. linkThumbTitles([document]);
  73. new MutationObserver( function(mutationSet)
  74. {
  75. mutationSet.forEach( function(mutation){ linkThumbTitles( mutation.addedNodes ); } );
  76. }).observe( document.body, { childList:true, subtree:true } );
  77. }
  78. var worksDisplay = document.getElementsByClassName("works_display")[0];
  79. if( worksDisplay )
  80. {
  81. var mainImage, mainLink = worksDisplay.querySelector("a[href*='mode=']");
  82. if( mainLink )
  83. mainLink.removeAttribute('target');//Make link open in same window
  84. var oClass = document.getElementsByClassName("original-image");
  85. if( oClass.length == 1 )//47235071
  86. {
  87. var worksDiv = worksDisplay.getElementsByTagName("div")[0];
  88. worksDisplay.removeChild( worksDiv );//Need to remove instead of hide to prevent double source search links in other script
  89. var link = worksDisplay.insertBefore( document.createElement("a"), worksDisplay.firstChild );
  90. mainImage = link.appendChild( fullSizeMedium ? document.createElement("img") : worksDiv.getElementsByTagName("img")[0] );
  91. fullsizeSrc = link.href = oClass[0].getAttribute("data-src");
  92. }
  93. else if( mainLink && mainLink.href.indexOf("mode=big") > 0 && (mainImage = mainLink.getElementsByTagName("img")[0]) !== null )//17099702
  94. {
  95. if( mainImage.src.indexOf("_m.") > 0 )
  96. mainLink.href = fullsizeSrc = mainImage.src.replace("_m.",".");
  97. else
  98. {
  99. //New thumbnails are always jpg, need to query mode=big page to get the right file extension.
  100. var req = new XMLHttpRequest();
  101. req.open( "GET", mainLink.href, true );
  102. req.onload = function()
  103. {
  104. mainLink.href = req.responseXML.getElementsByTagName("img")[0].src;
  105. if( fullSizeMedium )
  106. mainImage.src = mainLink.href;
  107. }
  108. req.responseType = "document";
  109. req.send(null);
  110. }
  111. }
  112. if( mainImage && fullSizeMedium )
  113. {
  114. if( fullsizeSrc )
  115. mainImage.src = fullsizeSrc;
  116. mainImage.setAttribute("style", "max-width: "+fullSizeWidth+"; height: auto; width: auto;");
  117. worksDisplay.style.width = fullSizeWidth;
  118. }
  119. }
  120. }
  121.  
  122. if( dontSayLazy && unlazyImage() && window == window.top )
  123. {
  124. //Initial page has lazy images; listen for more images added later
  125. new MutationObserver( function(mutationSet)
  126. {
  127. mutationSet.forEach( function(mutation)
  128. {
  129. for( var i = 0; i < mutation.addedNodes; i++ )
  130. unlazyImage( mutation.addedNodes[i] );
  131. } );
  132. }).observe( document.body, { childList:true, subtree:true } );
  133. }
  134.  
  135. //----------------------------------------------------------------//
  136.  
  137. function unlazyImage(target)
  138. {
  139. var images = ( target || document ).querySelectorAll("img[data-src]");
  140. for( var i = 0; i < images.length; i++ )
  141. images[i].src = images[i].getAttribute("data-src");
  142. return images.length;
  143. }
  144.  
  145. function pushTitleLink(list, link)
  146. {
  147. var matcher;
  148. if( link && link.href && (matcher = link.href.match(/illust_id=(\d+)/)) && matcher[1] > 0 )
  149. list.push({ "id": matcher[1], "link": link });
  150. }
  151.  
  152. function linkThumbTitles(targets)
  153. {
  154. var titleList = [];
  155. for( var i = 0; i < targets.length; i++ )
  156. {
  157. //search.php, bookmark.php, member_illust.php, new_illust.php, member.php (uploads), mypage.php (new works)
  158. var foundTitle = targets[i].querySelectorAll("a[href*='mode=medium'][href*='illust_id='] > .title");
  159. for( var j = 0; j < foundTitle.length; j++ )
  160. pushTitleLink( titleList, foundTitle[j].parentNode );
  161. //ranking.php
  162. foundTitle = targets[i].querySelectorAll(".ranking-item a.title[href*='mode=medium'][href*='illust_id=']");
  163. for( var j = 0; j < foundTitle.length; j++ )
  164. pushTitleLink( titleList, foundTitle[j] );
  165. //member_illust.php (what image was responding to)
  166. foundTitle = targets[i].querySelector(".worksImageresponseInfo a.response-out-work[href*='mode=medium'][href*='illust_id=']");
  167. if( foundTitle )
  168. pushTitleLink( titleList, foundTitle );
  169. //response.php, member_illust.php (before/after thumbnails), ?member.php (bookmarks)?
  170. var image = targets[i].querySelectorAll("li a[href*='mode=medium'][href*='illust_id='] img");
  171. for( var j = 0; j < image.length; j++ )
  172. {
  173. var page, title;
  174. for( page = image[j].parentNode; page.tagName != "A"; page = page.parentNode );
  175. //The prev/next thumbnails on mode=medium pages have text before/after the image. Text also follows the image on image responses listings.
  176. if( !(title = page.getElementsByClassName("title")[0]) && (title = page.lastChild).nodeName != '#text' && (title = page.firstChild).nodeName != '#text' )
  177. continue;//Can't find title element
  178. //Start title link at mode=medium and change later.
  179. var titleLink = document.createElement("a");
  180. titleLink.href = page.href;
  181. titleLink.style.color = "#333333";//Style used on some pages
  182. //Move the title out of the thumbnail link
  183. page.removeChild(title);
  184. titleLink.appendChild(title);
  185. page.parentNode.insertBefore( titleLink, page.nextSibling );
  186. pushTitleLink( titleList, titleLink );
  187. }
  188. }
  189. for( var i = 0; i < titleList.length; i++ )
  190. directLinkSingle( titleList[i] );
  191. }
  192.  
  193. //Query an image's mode=medium page.
  194. function directLinkSingle(title)
  195. {
  196. var req = new XMLHttpRequest();
  197. req.open( "GET", "http://www.pixiv.net/member_illust.php?mode=medium&illust_id="+title.id, true );
  198. req.onload = function()
  199. {
  200. var select = req.responseXML.getElementsByClassName("original-image");
  201. if( select.length == 1 )
  202. title.link.href = select[0].getAttribute("data-src");
  203. else if( (select = req.responseXML.querySelector(".works_display a[href*='mode=big'] img[src*='_m.']")) !== null )
  204. title.link.href = select.src.replace("_m.",".");
  205. else if( (select = req.responseXML.querySelector(".works_display a[href*='mode=manga']")) !== null )
  206. {
  207. title.link.href = select.href;
  208. var page = req.responseXML.querySelectorAll("ul.meta li")[1].textContent.match(/(\d+)P$/);
  209. if( page )
  210. ( title.link.firstChild.nodeName == '#text' ? title.link : title.link.firstChild ).title += " ("+page[1]+" pages)";
  211. }
  212. };
  213. req.responseType = "document";
  214. req.send(null);
  215. }