Easy Nav for Rule34.xxx

updated by JeyLists

  1. // ==UserScript==
  2. // @name Easy Nav for Rule34.xxx
  3. // @namespace http://use.i.E.your.homepage/
  4. // @version 0.74
  5. // @description updated by JeyLists
  6. // @match http*://*.rule34.xxx/*page=post*
  7. // @match http*://rule34.xxx/*page=post*
  8. // @copyright 2013+, Anonymous540
  9. // @require https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js
  10. // @grant GM_setValue
  11. // @grant GM_getValue
  12. // @grant GM_xmlhttpRequest
  13. // ==/UserScript==
  14.  
  15.  
  16. // console.debug($.fn.jquery);
  17. // console.debug($('.content span.thumb'))
  18.  
  19.  
  20. // CSS for navigation window
  21. image_nav_background_css = 'width: 100%; height: 100%; z-index: 100; position: absolute; background: rgba(0, 0, 0, 0.75);margin:0;display:none';
  22. image_nav_overlay_css = 'width: 100%; height: 100%;z-index: 101; position: absolute;margin:auto;display:none;text-align: center;pointer-events:none;';
  23. image_nav_content_css = 'pointer-events:auto;max-width: 100%; max-height: 100%;';
  24. image_nav_image_css = 'max-width:100%;max-height: 100%;vertical-align:middle;z-index:2';
  25. image_thumb_image_css = 'vertical-align: middle;z-index: 9000;display: inline-block;height: 32px;background-image: url(\'\/\/i.imgur.com\/itWV7LD.gif\');width: 32px;position:absolute;top: 50%;left: 50%;';
  26. arrow_style = 'height:100%; width:25px; background: rgba(0, 0, 0, 0.50); margin:0;color:white;display:inline-block;cursor:pointer; vertical-align: middle;position: absolute;';
  27. right_arrow_style = arrow_style+';right:0;';
  28. left_arrow_style = arrow_style+';left:0;';
  29. arrow_style_text = 'vertical-align: middle;';
  30. image_nav_text_overlay_css= 'position: absolute;bottom:0;width: 100%;text-align: center;right: 0px;background: rgba(255, 255, 255, 0.75);';
  31.  
  32.  
  33. // Creates the navigation window
  34. $('head').append('<style>'+
  35. '.image_nav_content .image_nav_text_overlay{'+
  36. ' display:none;'+
  37. ' }'+
  38. ' .image_nav_content:hover span.image_nav_text_overlay{'+
  39. ' display:inline-block;'+
  40. ' }'+
  41. '</style>');
  42.  
  43. $('body').prepend('<div class="image_nav_background" style="'+image_nav_background_css+'"></div><div class="image_nav_overlay" style="'+image_nav_overlay_css+'"><span class="image_nav_content" style="'+image_nav_content_css+'"><div class="left_arrow arrow" style="'+left_arrow_style+'"><span style="'+arrow_style_text+'"><<</span></div><div class="right_arrow" style="'+right_arrow_style+'"><span style="'+arrow_style_text+'">>></span></div><span style="'+image_nav_text_overlay_css+'" class="image_nav_text_overlay">Testing123</span><a href=""><div src="" style="'+image_thumb_image_css+'" class="thumb_img"></div><img src="" style="'+image_nav_image_css+'" data-real-height="" data-real-width="" data=image-number="" class="main_img"></a></span></div>').
  44.  
  45.  
  46.  
  47. // Turn most of the elements into a value
  48. $image_nav_background = $('.image_nav_background'); // No clue why this doesn't work. I link to the element directly instead.
  49. $image_nav_overlay = $('.image_nav_overlay');
  50. $nav_content = $('.image_nav_content');
  51. $nav_content_img = $('img.main_img', $nav_content);
  52. $nav_thumb_img = $('div.thumb_img', $nav_content);
  53. $left_arrow = $('.left_arrow', $nav_content);
  54. $right_arrow = $('.right_arrow', $nav_content);
  55. $text_overlay = $('.image_nav_text_overlay', $nav_content);
  56.  
  57. // Array which the images will be stored
  58. var Loaded_Images = {};
  59. var Loaded_Images_array = []; //Just the IDs for sorting
  60. var Loaded_Images_array_current; // Will be the current image
  61.  
  62. // Processes a URL and returns the page number
  63. function ProcessPagination(a){
  64. if(a !== undefined){
  65. // console.debug(a.attr('href'));
  66. var urlPage = a.match(/pid\=[0-9]{1,}/)[0].replace('pid=','');
  67. return ( parseInt(urlPage) /50 ) + 1;
  68. }else{
  69. return CurrentPage;
  70. }
  71. }
  72.  
  73.  
  74. // Some values which might change in the future
  75. var CurrentPage = parseInt($('#paginator .pagination b').text());
  76. var FirstPage = ProcessPagination($('#paginator .pagination [alt="first page"]').attr('href'));
  77. var LastPage = ProcessPagination($('#paginator .pagination [alt="last page"]').attr('href'));
  78. var ImagesPerPage = 50;
  79. var Navigation_Text = 'Easy Navigation';
  80. var Enable_Loading_Icon = true;
  81. var Setting_ImageLinkBegins = 'index.php?';
  82.  
  83.  
  84. // Sorts the image IDs into an array and also labels their page number and image number on the list
  85. function Sort_Object(SortObject){
  86. var Sorted = [];
  87. for(var key in SortObject)
  88. {
  89. Sorted.push(key);
  90. }
  91. return Sorted.sort(function(a, b) {
  92.  
  93. // Sort by page
  94. var PageCount = Loaded_Images[a].page - Loaded_Images[b].page;
  95. if(PageCount) return PageCount;
  96.  
  97. // If there is a tie, sort by image number
  98. var ImageCount = Loaded_Images[a].number - Loaded_Images[b].number;
  99. return ImageCount;
  100. });
  101. }
  102.  
  103.  
  104. // Pointless, I used this for debugging
  105. function Sort_images(){
  106. Loaded_Images_array = Sort_Object(Loaded_Images);
  107. /*
  108. var counting = 0
  109. var count_info = '';
  110. $.each(Loaded_Images_array,function(index,value){
  111. count_info+= 'Number: '+index+' | Page: '+Loaded_Images[value].page+' | Image: '+Loaded_Images[value].number+'\n';
  112. counting++
  113. })
  114. console.debug(counting+' Images sorted\n'+count_info)
  115. */
  116. }
  117.  
  118. // The function that is called everytime a new image is selected, either through navigating left, right, or clicking a link.
  119. function LoadImage(ImageID){
  120. Loaded_Images_array_current = Loaded_Images_array.indexOf(ImageID);
  121. // console.debug(Loaded_Images);
  122. var ImageThumb = Loaded_Images[ImageID].thumb;
  123. var ImageMain = Loaded_Images[ImageID].main;
  124. var LoadingImage = true;
  125.  
  126. // Sets the link on the image to the image page
  127. $nav_content_img.parent().attr('href',Loaded_Images[ImageID].link);
  128. // Formats all the tags into a list of links
  129. var ImageTagsFormatted = [];
  130. var ImageTags = Loaded_Images[ImageID].tags.split(" ");
  131. $.each(ImageTags, function(index, value) {
  132. ImageTagsFormatted.push('<a href="http://rule34.xxx/index.php?page=post&s=list&tags='+value+'">'+value+'</a>');
  133. });
  134. $('.image_nav_background').show();
  135. $image_nav_overlay.show();
  136. $nav_thumb_img.show();
  137. $text_overlay.empty().append('<a href="'+Loaded_Images[ImageID].link+'" class="main_image_direct_link">'+Loaded_Images[ImageID].filename+'</a> | Page '+Loaded_Images[ImageID].page+' | Image '+Loaded_Images[ImageID].number+'<br>'+ImageTagsFormatted.join(' | '));
  138. $nav_content_img
  139. .data('ImageId',ImageID);
  140. var current_status = Loaded_Images[ImageID].status;
  141. // Loads the image if it's already been verified previously.
  142. if(current_status == 'loaded' || current_status == 'error'){
  143. $nav_content_img.attr('src',ImageMain);
  144. if(current_status != 'loading')$nav_thumb_img.hide();
  145. $('.main_image_direct_link',$text_overlay).attr('href',ImageMain);
  146. RepositionMainImage();
  147. // Checks each image extension until it finds a working one
  148. }else if(current_status == 'waiting'){
  149. Loaded_Images[ImageID].status = 'loading';
  150. GM_xmlhttpRequest({
  151. method: "GET",
  152. url: '/'+Loaded_Images[ImageID].link,
  153. onload: function(retour) {
  154. Loaded_Images[ImageID].verified = true;
  155. var image;
  156. var ResponseHTML = $(retour.responseText);
  157. var ImageServer = $('div.content script:contains("image"):contains("domain"):contains("base_dir")',ResponseHTML).text();
  158. eval(ImageServer);
  159. var new_image_url = image.domain + "/" + image.base_dir + "/" + image.dir + "/" + image.img;
  160. Loaded_Images[ImageID].main = new_image_url;
  161. $("<img/>")
  162. .attr("src", new_image_url)
  163. .one('load',function(){
  164. Loaded_Images[ImageID].status = 'loaded';
  165. // Checks to make sure the successfully loading image actually is the one selected, since the load function for a previous image might be called after the user has switched to another.
  166. if($nav_content_img.data('ImageId') == ImageID){
  167. $nav_content_img.attr('src',new_image_url);
  168. $nav_thumb_img.hide();
  169. $('.main_image_direct_link',$text_overlay).attr('href',new_image_url);
  170. RepositionMainImage();
  171. }
  172. })
  173. .one('error',function(){
  174. Loaded_Images[ImageID].status = 'error';
  175. if($nav_content_img.data('ImageId') == ImageID){
  176. $nav_content_img.attr('src','/images/404.gif').one('load',function(){RepositionMainImage();});
  177. $nav_thumb_img.hide();
  178. $('.main_image_direct_link',$text_overlay).attr('href',new_image_url);
  179. }
  180. });
  181. }
  182. });
  183. }
  184. // Prevent left and right scrolling in background
  185. $('body').css({'overflow-x' : 'hidden', 'overflow-y': 'hidden'});
  186. }
  187.  
  188.  
  189.  
  190. // Function to add an image to the Loaded_Images object
  191. function AddImage(ImageID,ImageThumb,ImageMain,ImagePage,ImageNumber,ImageLink,ImageTags){
  192. Loaded_Images[ImageID] = {};
  193. Loaded_Images[ImageID].status = 'waiting';
  194. Loaded_Images[ImageID].id = ImageID;
  195. Loaded_Images[ImageID].thumb = ImageThumb;
  196. Loaded_Images[ImageID].main = ImageMain;
  197. Loaded_Images[ImageID].page = ImagePage;
  198. Loaded_Images[ImageID].number = ImageNumber;
  199. Loaded_Images[ImageID].link = ImageLink;
  200. Loaded_Images[ImageID].filename = ImageMain.match(/\/[0-9a-zA-Z]{1,}.[a-z]{3,4}\?/)[0].replace('/','').replace('?','');
  201. Loaded_Images[ImageID].tags = ImageTags;
  202. }
  203.  
  204. // Checks if Loading icon is enabled
  205. if(!Enable_Loading_Icon){
  206. $nav_thumb_img.css('background-image', '');
  207. }
  208.  
  209. // This is called when wanting to go 1 image forward, or backward. Usually when using the arrow keys or clicking the arrow buttons.
  210. function Next_Image(direction){
  211. // console.debug('Next Image clicked in '+direction+' direction')
  212. var NextCount = Loaded_Images_array_current;
  213. // Checks direction and adds or subtracts
  214. if(direction == 'right'){
  215. NextCount++;
  216. }else if(direction == 'left'){
  217. NextCount--;
  218. }else if(direction == 'up'){
  219. NextCount-=7;
  220. }else if(direction == 'down'){
  221. NextCount+=7;
  222. }
  223. // Checks to see if image exists. If not, loads the next page.
  224. var ImageID = Loaded_Images_array[NextCount];
  225. // console.debug(ImageID + 'loading')
  226. if(ImageID !== undefined){
  227. LoadImage(ImageID);
  228. }else{
  229. Load_Page(Loaded_Images[Loaded_Images_array[Loaded_Images_array_current]].id);
  230. }
  231. // console.debug(NextCount)
  232.  
  233. }
  234.  
  235.  
  236. // Loads the images from the next page
  237. function Load_Page(CurrentImageID){
  238. var Image_Number = Loaded_Images[CurrentImageID].number;
  239. var Image_Page = Loaded_Images[CurrentImageID].page;
  240. // Checks which page direction and if it's the end of the list.
  241. // Going towards the left
  242. var backPaging = (Image_Number <= 1 && Image_Page > 1);
  243. var FrontWall = (Image_Page == FirstPage);
  244. // Going towards the right
  245. var forwardPaging = (Image_Number >= ImagesPerPage && Image_Page >= 1);
  246. var RearWall = (Image_Number < ImagesPerPage && Image_Page == LastPage);
  247. var PageSelect;
  248. if(backPaging && !FrontWall){
  249. PageSelect = Image_Page-1;
  250. // console.debug('backpaging')
  251. }else if(forwardPaging && !RearWall){
  252. PageSelect = Image_Page+1;
  253. // console.debug('forwardPaging')
  254. }else{
  255. // console.debug('wall')
  256. PageSelect = Image_Page;
  257. }
  258.  
  259. // Takes the requested page and converts into a URL string to load.
  260. if(backPaging || forwardPaging){
  261. $nav_thumb_img.show();
  262. PageSelect -= 1;
  263. PageSelect = PageSelect*ImagesPerPage;
  264. var requestURL;
  265. if(document.URL.indexOf('pid=') > -1){
  266. requestURL = document.URL.replace(/pid\=[0-9]{1,}/,'pid='+PageSelect);
  267. }else{
  268. requestURL = document.URL+'&pid='+PageSelect;
  269. }
  270. // console.debug(requestURL+' Loading...')
  271. GM_xmlhttpRequest({
  272. method: "GET",
  273. url: requestURL,
  274. onload: function(retour) {
  275. // console.debug(retour)
  276. $nav_thumb_img.hide();
  277. ResponseHTML = $(retour.responseText);
  278. var ImageNumber = 0;
  279. $('.content span.thumb', ResponseHTML).each(function(){
  280. var $this_span = $(this);
  281. var ImageID = $this_span.attr('id');
  282. var ImageThumb = $('img.preview' ,$this_span).attr('src');
  283. var ImageTags = $('img.preview' ,$this_span).attr('alt');
  284. var ImagePage = parseInt($('#paginator .pagination b', ResponseHTML).text());
  285. var ImageMain = ImageThumb.replace('thumbnail_','').replace("/r34/thumbnails/",'//images/').replace("/rule34/thumbnails/",'/rule34//images/');
  286. var ImageLink = $('a[href^="'+Setting_ImageLinkBegins+'"]',$this_span).attr('href');
  287. // console.debug(ImageMain);
  288. // http://cdn.rule34.xxx/r34/thumbnails/1354/thumbnail_23a69eecacb1cd8c36045e45657800e8f257e950.jpg?1411722
  289. ImageNumber++;
  290. AddImage(ImageID,ImageThumb,ImageMain,ImagePage,ImageNumber,ImageLink,ImageTags);
  291. });
  292. Sort_images();
  293. var Cur_Image_ID = $('.image_nav_content img.main_img').data('ImageId');
  294. var Image_Number2 = Loaded_Images_array.indexOf(Cur_Image_ID);
  295. if(backPaging){
  296. Image_Number2--;
  297. // console.debug('backPaging')
  298. }else if(forwardPaging){
  299. Image_Number2++;
  300. // console.debug('forwardPaging')
  301. }
  302. // console.debug(Cur_Image_ID+' ID, Number: '+Image_Number2)
  303. New_Image = Loaded_Images_array[Image_Number2];
  304. // console.debug(New_Image)
  305. LoadImage(New_Image);
  306. }
  307. });
  308. }
  309. }
  310.  
  311. //Sets the image margins upon resizing the window
  312. function RepositionMainImage(){
  313. $nav_content_img.css('margin', 'auto');
  314. var ImgWidth = $nav_content_img.width();
  315. var WindowWidth = parseInt(window.innerWidth);
  316. var HMargin = (WindowWidth-ImgWidth)/2;
  317.  
  318. var ImgHeight = $nav_content_img.height();
  319. var WindowHeight = parseInt(window.innerHeight);
  320. var VMargin = (WindowHeight-ImgHeight)/2;
  321.  
  322. // console.debug(VMargin+'px '+HMargin+'px')
  323. $nav_content_img.css('margin', VMargin+'px '+HMargin+'px');
  324. $text_overlay.css({'margin-bottom' : VMargin+'px'});
  325. }
  326.  
  327. // Goes through each thumbnail on the page
  328. var ImageNumber=0;
  329. $('.content span.thumb').each(function(){
  330. var $this_span = $(this);
  331. var ImageID = $this_span.attr('id');
  332. var ImageThumb = $('img.preview' ,$this_span).attr('src');
  333. var ImageTags = $('img.preview' ,$this_span).attr('alt');
  334. var ImagePage = CurrentPage;
  335. var ImageLink = $('a[href^="'+Setting_ImageLinkBegins+'"]',$this_span).attr('href');
  336. // Turns the thumbnail link into the primary image link.
  337. var ImageMain = ImageThumb.replace('thumbnail_','').replace("/r34/thumbnails/",'//images/').replace("/rule34/thumbnails/",'/rule34//images/');
  338. ImageNumber++;
  339. // Add each image to the array
  340. AddImage(ImageID,ImageThumb,ImageMain,ImagePage,ImageNumber,ImageLink,ImageTags);
  341. // Creates a link under each thumbnail
  342. $this_span.append('<br><a href="#" class="image_nav_button" id="'+ImageID+'" data-image-id="'+ImageID+'">'+Navigation_Text+'</a>');
  343. var $image_button = $('a.image_nav_button', $this_span);
  344. // Makes that link open up the navigation window
  345. $image_button.click(function(){
  346. imageId_data = $image_button.data('imageId');
  347. LoadImage(imageId_data);
  348. window.scrollTo(0, 0);
  349. return false;
  350. });
  351. });
  352. delete ImageNumber;
  353.  
  354. // console.debug(Loaded_Images);
  355.  
  356. // Sort the images.
  357. Sort_images();
  358.  
  359. // Keyboard arrow key navigation
  360. document.onkeyup = function(evt){
  361. if($image_nav_overlay.is(":visible")){
  362. if(evt.which == 37 || evt.which == 65){
  363. Next_Image('left');
  364. }else if(evt.which == 39 || evt.which == 68){
  365. Next_Image('right');
  366. }else if(evt.which == 38 || evt.which == 87){
  367. Next_Image('up');
  368. }else if(evt.which == 40 || evt.which == 83){
  369. Next_Image('down');
  370. }
  371. }
  372. };
  373.  
  374. // Arrow button navigation
  375. $left_arrow.click(function(){Next_Image('left');});
  376. $right_arrow.click(function(){Next_Image('right');});
  377.  
  378. // Hide everything if black background is clicked.
  379.  
  380. $('.image_nav_background').click(function(){
  381. $('.image_nav_background').hide();
  382. $image_nav_overlay.hide();
  383. $nav_content_img.attr('src','');
  384. $('body').css({'overflow-x' : 'auto', 'overflow-y': 'auto'});
  385. });
  386.  
  387. // Keeps the main image centered
  388. $(window).resize(function() {
  389. if($nav_content_img.is(':visible')) {
  390. RepositionMainImage();
  391. }
  392. });
  393. // console.debug(Loaded_Images)