Easy Nav for Rule34.xxx

updated by JeyLists

คุณจะต้องติดตั้งส่วนขยาย เช่น Tampermonkey, Greasemonkey หรือ Violentmonkey เพื่อติดตั้งสคริปต์นี้

คุณจะต้องติดตั้งส่วนขยาย เช่น Tampermonkey หรือ Violentmonkey เพื่อติดตั้งสคริปต์นี้

คุณจะต้องติดตั้งส่วนขยาย เช่น Tampermonkey หรือ Violentmonkey เพื่อติดตั้งสคริปต์นี้

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name       Easy Nav for Rule34.xxx
// @namespace  http://use.i.E.your.homepage/
// @version    0.74
// @description  updated by JeyLists
// @match      http*://*.rule34.xxx/*page=post*
// @match      http*://rule34.xxx/*page=post*
// @copyright  2013+, Anonymous540
// @require 	https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_xmlhttpRequest
// ==/UserScript==


// console.debug($.fn.jquery);
// console.debug($('.content span.thumb'))


// CSS for navigation window
image_nav_background_css = 'width: 100%; height: 100%; z-index: 100; position: absolute; background: rgba(0, 0, 0, 0.75);margin:0;display:none';
image_nav_overlay_css = 'width: 100%; height: 100%;z-index: 101; position: absolute;margin:auto;display:none;text-align: center;pointer-events:none;';
image_nav_content_css = 'pointer-events:auto;max-width: 100%; max-height: 100%;';
image_nav_image_css = 'max-width:100%;max-height: 100%;vertical-align:middle;z-index:2';
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%;';
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;';
right_arrow_style = arrow_style+';right:0;';
left_arrow_style = arrow_style+';left:0;';
arrow_style_text = 'vertical-align: middle;';
image_nav_text_overlay_css= 'position: absolute;bottom:0;width: 100%;text-align: center;right: 0px;background: rgba(255, 255, 255, 0.75);';


// Creates the navigation window
$('head').append('<style>'+
'.image_nav_content .image_nav_text_overlay{'+
'		display:none;'+
'	}'+
'	.image_nav_content:hover span.image_nav_text_overlay{'+
'		display:inline-block;'+
'	}'+
'</style>');

$('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>').



// Turn most of the elements into a value
$image_nav_background = $('.image_nav_background'); // No clue why this doesn't work. I link to the element directly instead.
$image_nav_overlay = $('.image_nav_overlay');
$nav_content = $('.image_nav_content');
$nav_content_img = $('img.main_img', $nav_content);
$nav_thumb_img = $('div.thumb_img', $nav_content);
$left_arrow = $('.left_arrow', $nav_content);
$right_arrow = $('.right_arrow', $nav_content);
$text_overlay = $('.image_nav_text_overlay', $nav_content);

// Array which the images will be stored
var Loaded_Images = {};
var Loaded_Images_array = []; //Just the IDs for sorting
var Loaded_Images_array_current; // Will be the current image

// Processes a URL and returns the page number
function ProcessPagination(a){
	if(a !== undefined){
		// console.debug(a.attr('href'));
		var urlPage = a.match(/pid\=[0-9]{1,}/)[0].replace('pid=','');
		return ( parseInt(urlPage)  /50 ) + 1;
	}else{
		return CurrentPage;
	} 
}


// Some values which might change in the future
var CurrentPage = parseInt($('#paginator .pagination b').text());
var FirstPage = ProcessPagination($('#paginator .pagination [alt="first page"]').attr('href'));
var LastPage = ProcessPagination($('#paginator .pagination [alt="last page"]').attr('href'));
var ImagesPerPage = 50;
var Navigation_Text = 'Easy Navigation';
var Enable_Loading_Icon = true;
var Setting_ImageLinkBegins = 'index.php?';


// Sorts the image IDs into an array and also labels their page number and image number on the list
function Sort_Object(SortObject){
	var Sorted = [];
	for(var key in SortObject)
	{
		Sorted.push(key);
	}
	return Sorted.sort(function(a, b) {

		// Sort by page
		var PageCount = Loaded_Images[a].page - Loaded_Images[b].page;
		if(PageCount) return PageCount;

		// If there is a tie, sort by image number
		var ImageCount = Loaded_Images[a].number - Loaded_Images[b].number;
		return ImageCount;
	});
}


// Pointless, I used this for debugging
function Sort_images(){
	Loaded_Images_array = Sort_Object(Loaded_Images);
	/*
	var counting = 0
	var count_info = '';
	$.each(Loaded_Images_array,function(index,value){
		count_info+= 'Number: '+index+' | Page: '+Loaded_Images[value].page+' | Image: '+Loaded_Images[value].number+'\n';
		counting++
	})
	console.debug(counting+' Images sorted\n'+count_info)
	*/
}

// The function that is called everytime a new image is selected, either through navigating left, right, or clicking a link.
function LoadImage(ImageID){
	Loaded_Images_array_current = Loaded_Images_array.indexOf(ImageID);
	// console.debug(Loaded_Images);
	
	var ImageThumb = Loaded_Images[ImageID].thumb;
	var ImageMain = Loaded_Images[ImageID].main;
	var LoadingImage = true;

	
	// Sets the link on the image to the image page
	$nav_content_img.parent().attr('href',Loaded_Images[ImageID].link);
	
	// Formats all the tags into a list of links
	var ImageTagsFormatted = [];
	var ImageTags = Loaded_Images[ImageID].tags.split(" ");
	$.each(ImageTags, function(index, value) {
		ImageTagsFormatted.push('<a href="http://rule34.xxx/index.php?page=post&s=list&tags='+value+'">'+value+'</a>');
	});
	
	$('.image_nav_background').show();
	$image_nav_overlay.show();
	$nav_thumb_img.show();
	$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(' | '));
	
	$nav_content_img
	.data('ImageId',ImageID);
	
	var current_status = Loaded_Images[ImageID].status;
	
	// Loads the image if it's already been verified previously.
	if(current_status == 'loaded' || current_status == 'error'){
		$nav_content_img.attr('src',ImageMain);
		if(current_status != 'loading')$nav_thumb_img.hide();
		$('.main_image_direct_link',$text_overlay).attr('href',ImageMain);
		
		RepositionMainImage();
	
	// Checks each image extension until it finds a working one
	}else if(current_status == 'waiting'){
		Loaded_Images[ImageID].status = 'loading';
		GM_xmlhttpRequest({
			method: "GET",
			url: '/'+Loaded_Images[ImageID].link,
			onload: function(retour) {
				Loaded_Images[ImageID].verified = true;
				var image;
				var ResponseHTML = $(retour.responseText);
				var ImageServer = $('div.content script:contains("image"):contains("domain"):contains("base_dir")',ResponseHTML).text();
				eval(ImageServer);
				var new_image_url = image.domain + "/" + image.base_dir + "/" + image.dir + "/" + image.img;
				Loaded_Images[ImageID].main = new_image_url;
				$("<img/>")
					.attr("src", new_image_url)
					.one('load',function(){
						Loaded_Images[ImageID].status = 'loaded';
					// 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.
						if($nav_content_img.data('ImageId') == ImageID){
							$nav_content_img.attr('src',new_image_url);
							$nav_thumb_img.hide();
							$('.main_image_direct_link',$text_overlay).attr('href',new_image_url);
							RepositionMainImage();
						}						
					})
					.one('error',function(){
						Loaded_Images[ImageID].status = 'error';
						if($nav_content_img.data('ImageId') == ImageID){
							$nav_content_img.attr('src','/images/404.gif').one('load',function(){RepositionMainImage();});
							$nav_thumb_img.hide();
							$('.main_image_direct_link',$text_overlay).attr('href',new_image_url);
						}
					});
			}
		});
	}
	
	// Prevent left and right scrolling in background
	$('body').css({'overflow-x' : 'hidden', 'overflow-y': 'hidden'});
}



// Function to add an image to the Loaded_Images object
function AddImage(ImageID,ImageThumb,ImageMain,ImagePage,ImageNumber,ImageLink,ImageTags){
	Loaded_Images[ImageID] = {};
	Loaded_Images[ImageID].status = 'waiting';
	Loaded_Images[ImageID].id = ImageID;
	Loaded_Images[ImageID].thumb = ImageThumb;
	Loaded_Images[ImageID].main = ImageMain;
	Loaded_Images[ImageID].page = ImagePage;
	Loaded_Images[ImageID].number = ImageNumber;
	Loaded_Images[ImageID].link = ImageLink;
	Loaded_Images[ImageID].filename = ImageMain.match(/\/[0-9a-zA-Z]{1,}.[a-z]{3,4}\?/)[0].replace('/','').replace('?','');
	Loaded_Images[ImageID].tags = ImageTags;
}

// Checks if Loading icon is enabled
if(!Enable_Loading_Icon){
	$nav_thumb_img.css('background-image', '');
}

// This is called when wanting to go 1 image forward, or backward. Usually when using the arrow keys or clicking the arrow buttons.
function Next_Image(direction){
	// console.debug('Next Image clicked in '+direction+' direction')
	
	var NextCount = Loaded_Images_array_current;
	
	// Checks direction and adds or subtracts
	if(direction == 'right'){
		NextCount++;
	}else if(direction == 'left'){
		NextCount--;
	}else if(direction == 'up'){
		NextCount-=7;
	}else if(direction == 'down'){
		NextCount+=7;
	}
	
	// Checks to see if image exists. If not, loads the next page.
	var ImageID = Loaded_Images_array[NextCount];
	// console.debug(ImageID + 'loading')
	if(ImageID !== undefined){
		LoadImage(ImageID);
	}else{
		Load_Page(Loaded_Images[Loaded_Images_array[Loaded_Images_array_current]].id);
	}
	
	// console.debug(NextCount)

}


// Loads the images from the next page
 function Load_Page(CurrentImageID){
	
	
	var Image_Number = Loaded_Images[CurrentImageID].number;
	var Image_Page = Loaded_Images[CurrentImageID].page;
	
	// Checks which page direction and if it's the end of the list.
	
	// Going towards the left
	var backPaging = (Image_Number <= 1 && Image_Page > 1);
	var FrontWall = (Image_Page == FirstPage);
	
	// Going towards the right
	var forwardPaging = (Image_Number >= ImagesPerPage && Image_Page >= 1);
	var RearWall = (Image_Number < ImagesPerPage && Image_Page == LastPage);
    var PageSelect;
	if(backPaging && !FrontWall){
		PageSelect = Image_Page-1;
		// console.debug('backpaging')
	}else if(forwardPaging && !RearWall){
		PageSelect = Image_Page+1;
		// console.debug('forwardPaging')
	}else{
		// console.debug('wall')
		PageSelect = Image_Page;
	}

	
	
	// Takes the requested page and converts into a URL string to load.
	if(backPaging || forwardPaging){
	$nav_thumb_img.show();
	PageSelect -= 1;
	PageSelect = PageSelect*ImagesPerPage;
	var requestURL;
	if(document.URL.indexOf('pid=') > -1){
		requestURL = document.URL.replace(/pid\=[0-9]{1,}/,'pid='+PageSelect);
	}else{
		requestURL = document.URL+'&pid='+PageSelect;
	}
	// console.debug(requestURL+' Loading...')
	GM_xmlhttpRequest({
		method: "GET",
		url: requestURL,
		onload: function(retour) {
			// console.debug(retour)
			$nav_thumb_img.hide();
			ResponseHTML = $(retour.responseText);
			var ImageNumber = 0;
			$('.content span.thumb', ResponseHTML).each(function(){
			
				var $this_span = $(this);
				var ImageID = $this_span.attr('id');
				var ImageThumb = $('img.preview' ,$this_span).attr('src');
				var ImageTags = $('img.preview' ,$this_span).attr('alt');
				var ImagePage = parseInt($('#paginator .pagination b', ResponseHTML).text());
				var ImageMain = ImageThumb.replace('thumbnail_','').replace("/r34/thumbnails/",'//images/').replace("/rule34/thumbnails/",'/rule34//images/');
				var ImageLink = $('a[href^="'+Setting_ImageLinkBegins+'"]',$this_span).attr('href');
				
				// console.debug(ImageMain);
				// http://cdn.rule34.xxx/r34/thumbnails/1354/thumbnail_23a69eecacb1cd8c36045e45657800e8f257e950.jpg?1411722
			
				ImageNumber++;
				
				AddImage(ImageID,ImageThumb,ImageMain,ImagePage,ImageNumber,ImageLink,ImageTags);
				
			});
			
			Sort_images();
			var Cur_Image_ID = $('.image_nav_content img.main_img').data('ImageId');
			var Image_Number2 = Loaded_Images_array.indexOf(Cur_Image_ID);
			if(backPaging){
				Image_Number2--;
				// console.debug('backPaging')
			}else if(forwardPaging){
				Image_Number2++;
				// console.debug('forwardPaging')
			}
			// console.debug(Cur_Image_ID+' ID, Number: '+Image_Number2)			
			New_Image = Loaded_Images_array[Image_Number2];
			// console.debug(New_Image)
			LoadImage(New_Image);
			
		}
	});
	}
       
}

//Sets the image margins upon resizing the window
function RepositionMainImage(){	
	
	$nav_content_img.css('margin', 'auto');
		
	var ImgWidth = $nav_content_img.width();
	var WindowWidth = parseInt(window.innerWidth);
	var HMargin = (WindowWidth-ImgWidth)/2;

	var ImgHeight = $nav_content_img.height();
	var WindowHeight = parseInt(window.innerHeight);
	var VMargin = (WindowHeight-ImgHeight)/2;

	// console.debug(VMargin+'px '+HMargin+'px')
	$nav_content_img.css('margin', VMargin+'px '+HMargin+'px');
	$text_overlay.css({'margin-bottom' : VMargin+'px'});
	
	
	
}

// Goes through each thumbnail on the page
var ImageNumber=0;
$('.content span.thumb').each(function(){
	var $this_span = $(this);
	var ImageID = $this_span.attr('id');
	var ImageThumb = $('img.preview' ,$this_span).attr('src');
	var ImageTags = $('img.preview' ,$this_span).attr('alt');
	var ImagePage = CurrentPage;
	var ImageLink = $('a[href^="'+Setting_ImageLinkBegins+'"]',$this_span).attr('href');
	
	// Turns the thumbnail link into the primary image link.
	var ImageMain = ImageThumb.replace('thumbnail_','').replace("/r34/thumbnails/",'//images/').replace("/rule34/thumbnails/",'/rule34//images/');
	ImageNumber++;
	// Add each image to the array
	AddImage(ImageID,ImageThumb,ImageMain,ImagePage,ImageNumber,ImageLink,ImageTags);
	
	// Creates a link under each thumbnail
	$this_span.append('<br><a href="#" class="image_nav_button" id="'+ImageID+'" data-image-id="'+ImageID+'">'+Navigation_Text+'</a>');
	
	var $image_button = $('a.image_nav_button', $this_span);
	
	// Makes that link open up the navigation window
	$image_button.click(function(){
		
		imageId_data = $image_button.data('imageId');
		LoadImage(imageId_data);
		window.scrollTo(0, 0);
		return false;
	});
	
	
});
delete ImageNumber;

// console.debug(Loaded_Images);

// Sort the images.
Sort_images();

// Keyboard arrow key navigation
document.onkeyup = function(evt){    
	if($image_nav_overlay.is(":visible")){
		if(evt.which == 37 || evt.which == 65){
			Next_Image('left');
		}else if(evt.which == 39 || evt.which == 68){
			Next_Image('right');
		}else if(evt.which == 38 || evt.which == 87){
			Next_Image('up');
		}else if(evt.which == 40 || evt.which == 83){
			Next_Image('down');
		}
	}
};

// Arrow button navigation
$left_arrow.click(function(){Next_Image('left');});
$right_arrow.click(function(){Next_Image('right');});

// Hide everything if black background is clicked.

$('.image_nav_background').click(function(){
	$('.image_nav_background').hide();
	$image_nav_overlay.hide();
	$nav_content_img.attr('src','');
	$('body').css({'overflow-x' : 'auto', 'overflow-y': 'auto'});
});

// Keeps the main image centered
$(window).resize(function() {
	if($nav_content_img.is(':visible')) {	
		RepositionMainImage();		
	}
});
// console.debug(Loaded_Images)