Sleazy Fork is available in English.

Image Board Enhancer (Rule34, Gelbooru, Konachan, and more)

Auto Resize images and video on multiple image boards.

Version vom 12.07.2019. Aktuellste Version

// ==UserScript==
// @name         Image Board Enhancer (Rule34, Gelbooru, Konachan, and more)
// @namespace    ImageBoardEnhancer
// @version      0.5
// @description  Auto Resize images and video on multiple image boards.
// @author       DanDanDan
// @match        *://rule34.xxx/*
// @match        *://chan.sankakucomplex.com/*
// @match        *://idol.sankakucomplex.com/*
// @match        *://gelbooru.com/*
// @match        *://danbooru.donmai.us/*
// @match        *://konachan.com/*
// @match        *://yande.re/*
// @match        *://safebooru.org/*
// @match        *://rule34.paheal.net/*
// @match        *://rule34hentai.net/*
// @require      https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js
// @grant        none
// ==/UserScript==

(function() {
  'use strict';
	
	// Settings /////////////////////////////////////
    var resizeImageToFit = true;
    var resizeVideoToFit = true;
    var autoplayVideos = true;
    var videoVolume = 0;
    var autoScrollToContent = true;
    var updateWithWindowResize = true;
    var showFitButton = true;
    var showScrollButton = true;
    var showR34XXXLikeAndFavoriteButtons = true;
    var removeFluid = false;
    var widthMargin = 15;
    var heightMargin = 15;
	/////////////////////////////////////////////////
		
	// Do not edit below.
	
  // Create variables.
	var currentWindowWidth = 0;
	var currentWindowHeight = 0;
	var currentWindowAspect = 0;
	var contentTrueWidth = 0;
	var contentTrueHeight = 0;
	var contentTrueAspect = 0;
	var resizeReady = false;
	var debugMode = false;
	var r34buttons = false;
	var toolbarDOM  = '.sidebar form';
	var containerDOM = '#content';
	var imageDOM = '#image';
  var playerDOM;
  
  // Per-site DOM selection.
  if (document.location.hostname.toLowerCase() == 'rule34.xxx') { toolbarDOM = '.space'; r34buttons = showR34XXXLikeAndFavoriteButtons; playerDOM = '#gelcomVideoContainer'; };
  if (document.location.hostname.toLowerCase() == 'chan.sankakucomplex.com') { toolbarDOM = '#search-form'; }
  if (document.location.hostname.toLowerCase() == 'idol.sankakucomplex.com') { toolbarDOM = '#search-form'; }
  if (document.location.hostname.toLowerCase() == 'gelbooru.com') { toolbarDOM = '#tag-list form'; containerDOM = '.contain-push'; }
  if (document.location.hostname.toLowerCase() == 'danbooru.donmai.us') { toolbarDOM = '#search-box'; }
  if (document.location.hostname.toLowerCase() == 'rule34.paheal.net') { toolbarDOM = '#Navigationleft'; containerDOM = 'article'; imageDOM = '#main_image'; }
  if (document.location.hostname.toLowerCase() == 'rule34hentai.net') { toolbarDOM = '#Navigationleft'; containerDOM = 'article'; imageDOM = '#main_image'; playerDOM = '#fluid_video_wrapper_video-id'; }
  
  // Remove the Gelcom Video player.
  function removeFluidPlayer() {
    if (debugMode) console.log('removeFluidPlayer');
    $(playerDOM).replaceWith( $(containerDOM + ' video') );
    $(containerDOM + ' video').attr('id', 'image');
    document.getElementById('image').outerHTML = document.getElementById('image').outerHTML; // This removes all event listeners, it seems jquery tries to maintain  them.
    $(containerDOM + ' video').removeAttr('style');
    $(containerDOM + ' video').removeAttr('playsinline');
    $(containerDOM + ' video').removeAttr('webkit-playsinline');
    $(containerDOM + ' video').attr('controls', 'true');
    $(containerDOM + ' video').attr('autoplay', autoplayVideos);
  }
  
  // Get window size and aspect ratio.
	function getWindowProps() {
    if (debugMode) console.log('getWindowProps');
		currentWindowWidth = $( window ).width() - widthMargin;
		currentWindowHeight = $( window ).height() - heightMargin;
		if (currentWindowWidth != 0 && currentWindowHeight != 0)
			currentWindowAspect = currentWindowWidth / currentWindowHeight;
	}
	
  // Get the real size of the video or image.
	function getContentProps() {
    if (debugMode) console.log('getContentProps');
    
		if ($( containerDOM + ' video' ).length) {
      contentTrueWidth = $( containerDOM + ' video' )[0].videoWidth;
      contentTrueHeight = $( containerDOM + ' video' )[0].videoHeight;
    }
    
    else if ($( containerDOM + ' ' + imageDOM ).length) {
			var screenImage = $(containerDOM + ' ' + imageDOM);
			var theImage = new Image();
			theImage.src = screenImage.attr("src");
			contentTrueWidth = theImage.width;
			contentTrueHeight = theImage.height;
    }
    
    if (contentTrueWidth != 0 && contentTrueHeight != 0)
			contentTrueAspect = contentTrueWidth / contentTrueHeight;
    resizeReady = true;
	}
  
  // Resize the image (This resizes the video on some sites eg. sankakucomplex.com)
  function resizeImage(){
    if (debugMode) console.log('resizeImage');
    
    $( containerDOM + ' ' + imageDOM ).css('max-width', '');
    
    if (currentWindowAspect > contentTrueAspect) {
      $( containerDOM + ' ' + imageDOM )[0].width = currentWindowHeight * contentTrueAspect;
      $( containerDOM + ' ' + imageDOM )[0].height = currentWindowHeight;
    }
    
    else {
      $( containerDOM + ' ' + imageDOM )[0].width = currentWindowWidth;
      $( containerDOM + ' ' + imageDOM )[0].height = currentWindowWidth / contentTrueAspect;
    }
    
    // Remove css from images.
    $( containerDOM + ' ' + imageDOM ).removeAttr('style');
  }
  
  // Resize Fluid video player.
  function resizeFluidVideo(){
    if (debugMode) console.log('resizeFluidVideo');

    $( containerDOM + ' ' + playerDOM ).css('max-width', '');
    
    if (currentWindowAspect > contentTrueAspect) {
      $( containerDOM + ' ' + playerDOM ).css('width', currentWindowHeight * contentTrueAspect);
      $( containerDOM + ' ' + playerDOM ).css('height', currentWindowHeight);
    }
    
    else {
      $( containerDOM + ' ' + playerDOM ).css('width', currentWindowWidth);
      $( containerDOM + ' ' + playerDOM ).css('height', currentWindowWidth / contentTrueAspect);
    }
  }
  
  // Resize default video.
  function resizeVideo() {
    if (debugMode) console.log('resizeVideo');

    $( containerDOM + ' video' ).css('max-width', '');
    
    if (currentWindowAspect > contentTrueAspect) {
      $( containerDOM + ' video' )[0].width = currentWindowHeight * contentTrueAspect;
      $( containerDOM + ' video' )[0].height = currentWindowHeight;
    }
    
    else {
      $( containerDOM + ' video' )[0].width = currentWindowWidth;
      $( containerDOM + ' video' ).height = currentWindowWidth / contentTrueAspect;
    }
  }
  
  // Scroll the window to the video or image.
  function scrollToContent() {
    if (debugMode) console.log('scrollToContent');
    
    var contentID;
    
    if ($( containerDOM + ' ' + imageDOM ).length) contentID = containerDOM + ' ' + imageDOM;
    else if ($( containerDOM + ' ' + playerDOM ).length) contentID = containerDOM + ' ' + playerDOM;
    else if ($( containerDOM + ' video' ).length) contentID = containerDOM + ' video';
    
    $([document.documentElement, document.body]).animate({
        scrollTop: $(contentID).offset().top
    }, 0);
    $([document.documentElement, document.body]).animate({
        scrollLeft: $(contentID).offset().left
    }, 0);
  }
  
  // Check if resize is ready and what type of content to resize. 
  function fitContent() {
    if (debugMode) console.log('fitContent');
    
    if (resizeReady) {
      getWindowProps();
      if ($( containerDOM + ' ' + imageDOM ).length) {
        resizeImage();
      }
      
      else if ($( containerDOM + ' ' + playerDOM ).length) {
        resizeFluidVideo();
      }
      
      else if ($( containerDOM + ' video' ).length) {
        resizeVideo();
      }
    }
    
  }
  
  // Set the video auto play and volume settings.
  function videoSettings() {
    if (debugMode) console.log('videoSettings');
    
    $(containerDOM + ' video').prop('autoplay', autoplayVideos);
    $(containerDOM + ' video').prop('volume', videoVolume);
    $(containerDOM + ' video').prop('loop', true);
    if (autoplayVideos) $(containerDOM + ' video')[0].play(); else $(containerDOM + ' video')[0].pause();
  }
  
  // Remove the Gelcom player if present.
  if (removeFluid && $(playerDOM).length) removeFluidPlayer();
  
  // Get the image properties, resize, and scroll as the page is loading. 
  // If the image loads too quickly it wont fire the event.
  if ($( containerDOM + ' video' ).length || $( containerDOM + ' ' + imageDOM ).length) {
  	getContentProps();
    if(resizeImageToFit) fitContent();
    if (autoScrollToContent) scrollToContent();
  }
  
  // Add event listener to the image or video.
  if ($( containerDOM + ' video' ).length) {
    if (debugMode) console.log('Create video event listener');
    
    videoSettings();
    $( containerDOM + ' video' ).on('loadedmetadata', function() { //NOTE: replaced 'loadedmetadata' with 'canplay'
  		getContentProps();
      if (resizeVideoToFit) fitContent();
      if (autoScrollToContent) scrollToContent();
      $(containerDOM + ' video').play();
		});
  }
  
  else if ($( containerDOM + ' ' + imageDOM ).length) {
    if (debugMode) console.log('Create image event listener');
    
    $( containerDOM + ' ' + imageDOM ).on('load', function(){
      getContentProps();
      if(resizeImageToFit) fitContent();
      if (autoScrollToContent) scrollToContent();
    });
  }
  
  // Add the event listener to the window.
  if (updateWithWindowResize) {
    $( window ).resize(function() {
      fitContent();
    });
  }
  
  // Create the toolbar.
  if ($( containerDOM + ' ' + imageDOM ).length || $( containerDOM + ' video' ).length) {
    if (debugMode) console.log('Create toolbar');
    
    $( toolbarDOM ).after( "<div id='ibenhancer'></div>" );
    
    if (showFitButton) {
      $( "#ibenhancer" ).append( "<button id='fitContentButton' style='margin-top: 3px; background: #fff; border: 1px solid #dadada; width: 50px;'>Fit</button>" );
      $( "#fitContentButton" ).click(function(){getContentProps();fitContent()});
    }
    
    if (showScrollButton) {
      $( "#ibenhancer" ).append( "<button id='scrollContentButton' style='margin-top: 3px; background: #fff; border: 1px solid #dadada; width: 60px;'>Scroll</button>" );
      $( "#scrollContentButton" ).click(scrollToContent);
    }
  
  	// Add the like and favorite button to rule34.xxx
  	if (r34buttons) {
    	if (debugMode) console.log('r34buttons');
    
    	$( "#ibenhancer" ).append('<br><img id="like-butt" class="custom-button" src="https://i.imgur.com/Kh1HzGr.png" alt="like"><img id="favorite-butt" class="custom-button" src="https://i.imgur.com/dTpBrIj.png" alt="favorite">');
    	$("#like-butt").click(function() {
        $("#stats > ul > li:contains('(vote up)') > a:contains('up')").click();
    	});
    	$("#favorite-butt").click(function() {
        $("#stats + div > ul > li > a:contains('Add to favorites')").click();
    	});
    
    	addGlobalStyle(`
				img.custom-button {
					cursor: pointer;
					width: 35px;
					padding: 3px;
					margin: 0;
					border-radius: 20px;
				}
				.custom-button:hover {
					background-color: rgba(255,255,255,.5);
				}
				.custom-button:active {
					background-color: rgba(255,255,255,1);
				}
			`);
  	}
  }
  
  function addGlobalStyle(css) {
    if (debugMode) console.log('addGlobalStyle');
    var head, style;
    head = document.getElementsByTagName('head')[0];
    if (!head) { return; }
    style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = css;
    head.appendChild(style);
  }
  
  if (debugMode) console.log('End of script.');
})();