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

Auto Resize images and video on multiple image boards.

As of 2019-07-09. See the latest version.

// ==UserScript==
// @name         Image Board Enhancer (Rule34, Gelbooru, Konachan, and more)
// @namespace    ImageBoardEnhancer
// @version      0.2
// @description  Auto Resize images and video on multiple image boards.
// @author       DanDanDan
// @match        *://rule34.xxx/*
// @match        *://chan.sankakucomplex.com/post/show/*
// @match        *://idol.sankakucomplex.com/post/show/*
// @match        *://gelbooru.com/*
// @match        *://danbooru.donmai.us/*
// @match        *://konachan.com/post/show/*
// @match        *://yande.re/post/show/*
// @match        *://safebooru.org/*
// @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 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 = true;
  var toolbarElement  = '.sidebar form';
  var r34buttons = false;
  var containerDOM = '#content';
  
  // Per-site DOM selection.
  if (document.location.hostname.toLowerCase() == 'rule34.xxx') { toolbarElement = '.space'; r34buttons = showR34XXXLikeAndFavoriteButtons };
  if (document.location.hostname.toLowerCase() == 'chan.sankakucomplex.com') toolbarElement = '#search-form';
  if (document.location.hostname.toLowerCase() == 'idol.sankakucomplex.com') toolbarElement = '#search-form';
  if (document.location.hostname.toLowerCase() == 'gelbooru.com') {toolbarElement = '#tag-list form'; containerDOM = '.contain-push';}
  
  // 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;
      console.log(contentTrueWidth);
    } else if ($( containerDOM + ' #image' ).length) {
      
			var screenImage = $(containerDOM + ' #image');
			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 sankakucomplex.com)
  function resizeImage(){
    if (debugMode) console.log('resizeImage');
    if (currentWindowAspect > contentTrueAspect) {
      $( containerDOM + ' #image' )[0].width = currentWindowHeight * contentTrueAspect;
      $( containerDOM + ' #image' )[0].height = currentWindowHeight;
    } else {
      $( containerDOM + ' #image' )[0].width = currentWindowWidth;
      $( containerDOM + ' #image' )[0].height = currentWindowWidth / contentTrueAspect;
    }
    // Remove css width from Gelbooru images
    if (document.location.hostname.toLowerCase() == 'gelbooru.com') {
      $( containerDOM + ' #image' ).css('width', '');
    }
  }
  
  // Resize Gelcom video player (Used for Rule34.xxx)
  function resizeGelcomVideo(){
    if (debugMode) console.log('resizeGelcomVideo');

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

    $( containerDOM + ' video' ).css('max-width', '');
    if (currentWindowAspect > contentTrueAspect) {
      $( containerDOM + ' video' ).css('width', currentWindowHeight * contentTrueAspect);
      $( containerDOM + ' video' ).css('height', currentWindowHeight);
    } else {
      $( containerDOM + ' video' ).css('width', currentWindowWidth);
      $( containerDOM + ' video' ).css('height', currentWindowWidth / contentTrueAspect);
    }
  }
  
  // Scroll the window to the video or image.
  function scrollToContent() {
    if (debugMode) console.log('scrollToContent');
    var contentID;
    if ($( containerDOM + ' #image' ).length) contentID = containerDOM + ' #image';
    else if ($( containerDOM + ' #gelcomVideoContainer' ).length) contentID = containerDOM + ' #gelcomVideoContainer';
    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 + ' #image' ).length) {
        resizeImage();
      } else if ($( containerDOM + ' #gelcomVideoContainer' ).length) {
        resizeGelcomVideo();
      } else if ($( containerDOM + ' video' ).length) {
        resizeVideo();
      }
    }
    
  }
  
  // Set the video auto play and volume settings.
  function videoSettings() {
    if (debugMode) console.log('videoSettings');
    if (document.location.hostname.toLowerCase() == 'rule34.xxx') {
      $(containerDOM + ' #gelcomVideoPlayer').prop('autoplay', autoplayVideos);
      $(containerDOM + ' #gelcomVideoPlayer').prop('volume', videoVolume);
    }
    if (document.location.hostname.toLowerCase() == 'chan.sankakucomplex.com' || document.location.hostname.toLowerCase() == 'idol.sankakucomplex.com') {
      $(containerDOM + ' video')[0].autoplay = autoplayVideos;
      $(containerDOM + ' video').prop('volume', videoVolume);
    }
  }
  
  // Add event listener to the image or video.
  if ($( containerDOM + ' video' ).length) {
    if (debugMode) console.log('Create video event listener');
    $( containerDOM + ' video' ).on('loadedmetadata', function() {
			videoSettings();
  		getContentProps();
      if (resizeVideoToFit) fitContent();
      if (autoScrollToContent) scrollToContent();
		});
  } else if ($( containerDOM + ' #image' ).length) {
    if (debugMode) console.log('Create image event listener');
    	// Get the image properties, resize, and scroll as the page is loading. 
      // If the image loads too quickly it wont fire the event.
    	getContentProps(); 
      if(resizeImageToFit) fitContent();
      if (autoScrollToContent) scrollToContent();
    
    $( containerDOM + ' #image' ).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 + ' #image' ).length || $( containerDOM + ' video' ).length) {
    if (debugMode) console.log('Create toolbar');
    $( toolbarElement ).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.');
})();