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

Auto Resize images and video on multiple image boards and enlarges thumbnails on mouse hover and adds content type icons to them.

2021/02/24時点のページです。最新版はこちら。

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください。
// ==UserScript==
// @name        Image Board Enhancer (Rule34, Gelbooru, e621, and more)
// @namespace   ImageBoardEnhancer
// @version     1.4
// @description Auto Resize images and video on multiple image boards and enlarges thumbnails on mouse hover and adds content type icons to them.
// @author      DanDanDan
// @match       *://rule34.xxx/*
// @match       *://chan.sankakucomplex.com/*
// @match       *://idol.sankakucomplex.com/*
// @match       *://gelbooru.com/*
// @match       *://danbooru.donmai.us/*
// @match       *://konachan.com/*
// @match       *://konachan.net/*
// @match       *://yande.re/*
// @match       *://safebooru.org/*
// @match       *://rule34.paheal.net/*
// @match       *://rule34hentai.net/*
// @match       *://e621.net/*
// @match       *://e926.net/*
// @match       *://tbib.org/*
// @match       *://behoimi.org/*
// @require     https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js
// @require     https://greasyfork.org/scripts/420841-image-board-enhancer-icons/code/Image%20Board%20Enhancer%20Icons.js?version=903872
// @require     https://greasyfork.org/scripts/420842-vanilla-js-wheel-zoom/code/vanilla-js-wheel-zoom.js?version=895198
// @grant       GM.setValue
// @grant       GM.getValue
// ==/UserScript==
(async () => {
  'use strict';

  try {

    var resizeImageToFit = await GM.getValue('resizeImageToFit', true);
    var resizeVideoToFit = await GM.getValue('resizeVideoToFit', true);
    var autoplayVideos = await GM.getValue('autoplayVideos', true);
    var autoScrollToContent = await GM.getValue('autoScrollToContent', true);
    var updateWithWindowResize = await GM.getValue('updateWithWindowResize', true);
    var updateScrollOnWindowResize = await GM.getValue('updateScrollOnWindowResize', true);
    var showFitButton = await GM.getValue('showFitButton', true);
    var showScrollButton = await GM.getValue('showScrollButton', true);
    var showVotingButtons = await GM.getValue('showVotingButtons', true);
    var removeFluid = await GM.getValue('removeFluid', false);
    var videoVolume = await GM.getValue('videoVolume', 0);
    var enableEnhancedThumbnails = await GM.getValue('enableEnhancedThumbnails', true);
    var alwaysShowScrollbars = await GM.getValue('alwaysShowScrollbars', false);
    var enableZoomableImage = await GM.getValue('enableZoomableImage', true);
    var maxZoom = await GM.getValue('maxZoom', 1);
    var zoomSpeed = await GM.getValue('zoomSpeed', 7);
    var resizeButton = await GM.getValue('resizeButton', 'BracketLeft');
    var scrollButton = await GM.getValue('scrollButton', 'BracketRight');
    var iconSize = await GM.getValue('iconSize', 36);

    var hiddenIcons = await GM.getValue('hiddenIcons', []);

    var customSites = await GM.getValue('customSites', {});

    // Create variables.
    var currentWindowWidth = 0;
    var currentWindowHeight = 0;
    var currentWindowAspect = 0;
    var contentTrueWidth = 0;
    var contentTrueHeight = 0;
    var contentTrueAspect = 0;
    var resizeReady = false;
    var toolbarDOM = '.sidebar form';
    var containerDOM = '#content';
    var imageDOM = '#image';
    var playerDOM;
    var changeKeyboardShortcut = false;
    var containerAlignment = '';
    var thumbnailDOM = '.thumb';
    var thumbnails = [];
    var animationTagIsGif = false;
    var urlParams = new URLSearchParams(window.location.search);
    var unsupportedThumbnailPage = false;
    var waitingForZoom = false;
    var wzoom;
    var placeSettingsAfter = true;
    var loggedin = false;

    var debugMode = false;
    var keepThumbOpen = false;

    // Per-site DOM selection.
    if (document.location.hostname.toLowerCase() == 'rule34.xxx') { toolbarDOM = '.sidebar > div'; playerDOM = '#gelcomVideoContainer'; animationTagIsGif = true; loggedin = true; /* no loggedin indercator */ }
    else if (document.location.hostname.toLowerCase() == 'chan.sankakucomplex.com' || document.location.hostname.toLowerCase() == 'idol.sankakucomplex.com') { toolbarDOM = '#search-form'; loggedin = ($('#navbar li a:contains("My Account")').length > 0); }
    else if (document.location.hostname.toLowerCase() == 'gelbooru.com') { toolbarDOM = 'section.aside > *'; placeSettingsAfter = false; containerDOM = '#container'; thumbnailDOM = '.thumbnail-preview'; loggedin = true; /* no loggedin indercator */ }
    else if (document.location.hostname.toLowerCase() == 'danbooru.donmai.us') { toolbarDOM = '#search-box'; thumbnailDOM = '.post-preview'; loggedin = !($('#nav-login').length > 0); }
    else if (document.location.hostname.toLowerCase() == 'konachan.com' || document.location.hostname.toLowerCase() == 'konachan.net') { animationTagIsGif = true; loggedin = ($('.standard-vote-widget a').length > 0); }
    else if (document.location.hostname.toLowerCase() == 'yande.re') { loggedin = ($('.standard-vote-widget a').length > 0); }
    else if (document.location.hostname.toLowerCase() == 'safebooru.org') { loggedin = true; /* no loggedin indercator */ }
    else if (document.location.hostname.toLowerCase() == 'tbib.org') { loggedin = true; /* no loggedin indercator */ }
    else if (document.location.hostname.toLowerCase() == 'behoimi.org') { loggedin = ($('#navbar li a:contains("My Account")').length > 0); }
    else if (document.location.hostname.toLowerCase() == 'rule34.paheal.net') { toolbarDOM = '#Navigationleft'; containerDOM = 'article'; imageDOM = '#main_image'; containerAlignment = 'margin-left: auto;'; /* cannot test loggedin since i dont have an account */ }
    else if (document.location.hostname.toLowerCase() == 'rule34hentai.net') { toolbarDOM = '#Navigationleft'; containerDOM = 'article'; imageDOM = '#main_image'; playerDOM = '#fluid_video_wrapper_video-id'; containerAlignment = 'margin-left: auto;'; loggedin = !(jQuery('#Loginhead').length > 0) }
    else if (document.location.hostname.toLowerCase() == 'e621.net' || document.location.hostname.toLowerCase() == 'e926.net') { toolbarDOM = '#search-box'; thumbnailDOM = '.post-preview'; animationTagIsGif = true; loggedin = !(jQuery('#nav-sign-in').length > 0) }
    // Custom site DOM selection.
    else if (customSites[document.location.hostname.toLowerCase()]) {
      var obj = customSites[document.location.hostname.toLowerCase()];
      if (debugMode) console.log(obj, 'obj')
      if (obj.toolbarDOM) toolbarDOM = obj.toolbarDOM;
      if (obj.containerDOM) containerDOM = obj.containerDOM;
      if (obj.imageDOM) imageDOM = obj.imageDOM;
      if (obj.thumbnailDOM) thumbnailDOM = obj.thumbnailDOM
      $("body").append("<button id='ibenhancerDeleteConfigButton' style='position: absolute; top: 0px; right: 0px; z-index: 9999999; color: black; background-color: whitesmoke; font-size: 12px;'>Delete site config.</button>");
      $("#ibenhancerDeleteConfigButton").click(deleteSiteConfig);
    }
    // Default site DOM and add setup button.
    else {
      // Add setup button to websites wihtout a config.
      $("body").append("<button id='ibenhancerSetupButton' style='position: absolute; top: 0px; right: 0px; z-index: 9999999; color: black; background-color: whitesmoke; font-size: 12px;'>Setup Image Board Enhancer</button>");
      $("#ibenhancerSetupButton").click(addSiteConfig);
      console.warn('This site is not supported, but may still work.');
    }

    // Add site config.
    function addSiteConfig() {
      var config = JSON.parse(prompt("Enter config in JSON format.", '{"toolbarDOM": ".sidebar form", "containerDOM": "#content", "imageDOM": "#image", "thumbnailDOM": ".thumb" }'));

      if (config === null || !config || config == {}) {
        alert('Config not valid.');
      } else {
        customSites[document.location.hostname.toLowerCase()] = config;
        if (debugMode) console.log(customSites);
        GM.setValue('customSites', customSites);
        alert('Config saved.')
        location.reload();
      }
    }

    // Delete site config.
    function deleteSiteConfig() {
      delete customSites[document.location.hostname.toLowerCase()];
      GM.setValue('customSites', customSites);
      alert('Config deleted.')
      location.reload();
    }

    // Remove the Fluid Video player.
    function removeFluidPlayer() {
      if (debugMode) console.log('removeFluidPlayer');
      // Create a new video player with the source of the original. This will break blob content if any sites start using DRM.
      $(playerDOM).replaceWith("<video src='" + ($(containerDOM + ' video').attr('src') || $(containerDOM + ' video source').attr('src')) + "' controls='true' />");

      // Old method.
      // $(playerDOM).replaceWith($(containerDOM + ' video'));
      // $(containerDOM + ' video').attr('id', 'image');
      // document.querySelector(imageDOM).outerHTML = document.querySelector(imageDOM).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 = document.documentElement.clientWidth;
      currentWindowHeight = document.documentElement.clientHeight;
      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');
      if (enableZoomableImage && !$(containerDOM + ' video').length) $(containerDOM + ' ' + imageDOM).css({ cursor: 'zoom-in' });
    }

    // 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(delay) {
      if (debugMode) console.log('scrollToContent');

      setTimeout(function () {
        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 + 1
        }, 0);
        $([document.documentElement, document.body]).animate({
          scrollLeft: $(contentID).offset().left + 1
        }, 0);
      }, delay);

    }

    // Check if resize is ready and what type of content to resize. 
    function fitContent(delay) {
      if (debugMode) console.log('fitContent');
      setTimeout(function () {
        if (resizeReady) {
          getWindowProps();
          if ($(containerDOM + ' ' + imageDOM).length) {
            resizeImage();
          }

          else if ($(containerDOM + ' ' + playerDOM).length) {
            resizeFluidVideo();
          }

          else if ($(containerDOM + ' video').length) {
            resizeVideo();
          }
        }
      }, delay);


    }

    // 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) {

      // Show Scrollbars
      if (alwaysShowScrollbars) $('html').css({ overflow: 'scroll' });

      getContentProps();
      if (resizeImageToFit) fitContent(200);
      if (autoScrollToContent) scrollToContent(200);
    }

    // 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(200);
        if (autoScrollToContent) scrollToContent(200);
        $(containerDOM + ' video').play();

      });
    }

    else if ($(containerDOM + ' ' + imageDOM).length) {
      if (debugMode) console.log('Create image event listener');

      $(containerDOM + ' ' + imageDOM).on('load', function () {
        if (waitingForZoom) {
          console.log('Waited for zoom');
          setTimeout(openZoom, 16);
          waitingForZoom = false;
        }
        getContentProps();
        if (resizeImageToFit) fitContent(200);
        if (autoScrollToContent) scrollToContent(200);
      });
    }

    // Add the event listener to the window.
    if (updateWithWindowResize) {
      $(window).resize(function () {
        fitContent(0);
        if (updateScrollOnWindowResize) scrollToContent(0);
      });
    }

    // Setting Functions
    function showSettings() {
      $("#ibenhancerSettings").addClass('show');
      $("#ibenhancerSettings-blocker").addClass('show');
      $("html").addClass('ibenhancerSettingVisible');
    }
    function hideSettings() {
      $("#ibenhancerSettings").removeClass('show');
      $("#ibenhancerSettings-blocker").removeClass('show');
      $("html").removeClass('ibenhancerSettingVisible');

      // Reset the form to original state.
      $("#resizeImageToFitCheckbox").prop('checked', resizeImageToFit);
      $("#resizeVideoToFitCheckbox").prop('checked', resizeVideoToFit);
      $("#autoplayVideosCheckbox").prop('checked', autoplayVideos);
      $("#autoScrollToContentCheckbox").prop('checked', autoScrollToContent);
      $("#updateWithWindowResizeCheckbox").prop('checked', updateWithWindowResize);
      $("#updateScrollOnWindowResizeCheckbox").prop('checked', updateScrollOnWindowResize);
      $("#showFitButtonCheckbox").prop('checked', showFitButton);
      $("#showScrollButtonCheckbox").prop('checked', showScrollButton);
      $("#showVotingButtonsCheckbox").prop('checked', showVotingButtons);
      $("#removeFluidCheckbox").prop('checked', removeFluid);
      $("#enableEnhancedThumbnailsCheckbox").prop('checked', enableEnhancedThumbnails);
      $("#alwaysShowScrollbarsCheckbox").prop('checked', alwaysShowScrollbars);
      $("#enableZoomableImageCheckbox").prop('checked', enableZoomableImage);

      $("#maxZoomInput").val(maxZoom);
      $("#zoomSpeedInput").val(zoomSpeed);
      $("#videoVolumeInput").val(videoVolume);

      $("#iconSizeInput").val(iconSize);

      $("#hideIconGifCheckbox").prop('checked', hiddenIcons.includes("gif"));
      $("#hideIconVideoCheckbox").prop('checked', hiddenIcons.includes("video"));
      $("#hideIconSoundCheckbox").prop('checked', hiddenIcons.includes("sound"));
      $("#hideIconFlashCheckbox").prop('checked', hiddenIcons.includes("flash"));
      $("#hideIconStraightCheckbox").prop('checked', hiddenIcons.includes("straight"));
      $("#hideIconGayCheckbox").prop('checked', hiddenIcons.includes("gay"));
      $("#hideIconLesbianCheckbox").prop('checked', hiddenIcons.includes("lesbian"));
      $("#hideIconTransCheckbox").prop('checked', hiddenIcons.includes("trans"));
      $("#hideIconTrapCheckbox").prop('checked', hiddenIcons.includes("trap"));
      $("#hideIconThreeDCheckbox").prop('checked', hiddenIcons.includes("threeD"));
      $("#hideIconLoliCheckbox").prop('checked', hiddenIcons.includes("loli"));
      $("#hideIconShotaCheckbox").prop('checked', hiddenIcons.includes("shota"));
      $("#hideIconGoreDeathCheckbox").prop('checked', hiddenIcons.includes("goreDeath"));
      $("#hideIconPregnantCheckbox").prop('checked', hiddenIcons.includes("pregnant"));
      $("#hideIconBestialityCheckbox").prop('checked', hiddenIcons.includes("bestiality"));
      $("#hideIconFeetCheckbox").prop('checked', hiddenIcons.includes("feet"));
      $("#hideIconBondageCheckbox").prop('checked', hiddenIcons.includes("bondage"));
      $("#hideIconPoopCheckbox").prop('checked', hiddenIcons.includes("poop"));
      $("#hideIconPissCheckbox").prop('checked', hiddenIcons.includes("piss"));
      $("#hideIconGroupCheckbox").prop('checked', hiddenIcons.includes("group"));
      $("#hideIconIncestCheckbox").prop('checked', hiddenIcons.includes("incest"));
      $("#hideIconSafeCheckbox").prop('checked', hiddenIcons.includes("safe"));
      $("#hideIconQuestionableCheckbox").prop('checked', hiddenIcons.includes("questionable"));
      $("#hideIconExplicitCheckbox").prop('checked', hiddenIcons.includes("explicit"));
      $("#hideIconBukkakeCheckbox").prop('checked', hiddenIcons.includes("bukkake"));
      $("#hideIconTentaclesCheckbox").prop('checked', hiddenIcons.includes("tentacles"));
      $("#hideIconRapeCheckbox").prop('checked', hiddenIcons.includes("rape"));
      $("#hideIconPublicCheckbox").prop('checked', hiddenIcons.includes("public"));
      $("#hideIconFurryCheckbox").prop('checked', hiddenIcons.includes("furry"));
      $("#hideIconFatCheckbox").prop('checked', hiddenIcons.includes("fat"));
      $("#hideIconHypnosisCheckbox").prop('checked', hiddenIcons.includes("hypnosis"));
      $("#hideIconNtrCheckbox").prop('checked', hiddenIcons.includes("ntr"));
      $("#hideIconFemdomCheckbox").prop('checked', hiddenIcons.includes("femdom"));
    }
    function changeResizeButtonClicked() {
      $('#resizeButton').html('?');
      changeKeyboardShortcut = 'resizeButton';
    }
    function changeScrollButtonClicked() {
      $('#scrollButton').html('?');
      changeKeyboardShortcut = 'scrollButton';
    }
    function saveSettings() {
      GM.setValue('resizeImageToFit', $('#resizeImageToFitCheckbox').is(':checked'));

      GM.setValue('resizeVideoToFit', $('#resizeVideoToFitCheckbox').is(':checked'));

      GM.setValue('autoplayVideos', $('#autoplayVideosCheckbox').is(':checked'));

      GM.setValue('autoScrollToContent', $('#autoScrollToContentCheckbox').is(':checked'));

      GM.setValue('updateScrollOnWindowResize', $('#updateScrollOnWindowResizeCheckbox').is(':checked'));

      GM.setValue('updateWithWindowResize', $('#updateWithWindowResizeCheckbox').is(':checked'));

      GM.setValue('showFitButton', $('#showFitButtonCheckbox').is(':checked'));

      GM.setValue('showScrollButton', $('#showScrollButtonCheckbox').is(':checked'));

      GM.setValue('showVotingButtons', $('#showVotingButtonsCheckbox').is(':checked'));

      GM.setValue('removeFluid', $('#removeFluidCheckbox').is(':checked'));

      GM.setValue('videoVolume', $('#videoVolumeInput').val());

      GM.setValue('enableEnhancedThumbnails', $('#enableEnhancedThumbnailsCheckbox').is(':checked'));

      GM.setValue('alwaysShowScrollbars', $('#alwaysShowScrollbarsCheckbox').is(':checked'));

      GM.setValue('enableZoomableImage', $('#enableZoomableImageCheckbox').is(':checked'));

      GM.setValue('maxZoom', $('#maxZoomInput').val());
      GM.setValue('zoomSpeed', $('#zoomSpeedInput').val());

      GM.setValue('iconSize', $('#iconSizeInput').val());

      GM.setValue('resizeButton', resizeButton);
      GM.setValue('scrollButton', scrollButton);

      var newHiddenIcons = [];

      if ($('#hideIconGifCheckbox').is(':checked')) newHiddenIcons.push('gif');
      if ($('#hideIconVideoCheckbox').is(':checked')) newHiddenIcons.push('video');
      if ($('#hideIconSoundCheckbox').is(':checked')) newHiddenIcons.push('sound');
      if ($('#hideIconFlashCheckbox').is(':checked')) newHiddenIcons.push('flash');
      if ($('#hideIconStraightCheckbox').is(':checked')) newHiddenIcons.push('straight');
      if ($('#hideIconGayCheckbox').is(':checked')) newHiddenIcons.push('gay');
      if ($('#hideIconLesbianCheckbox').is(':checked')) newHiddenIcons.push('lesbian');
      if ($('#hideIconTransCheckbox').is(':checked')) newHiddenIcons.push('trans');
      if ($('#hideIconTrapCheckbox').is(':checked')) newHiddenIcons.push('trap');
      if ($('#hideIconThreeDCheckbox').is(':checked')) newHiddenIcons.push('threeD');
      if ($('#hideIconLoliCheckbox').is(':checked')) newHiddenIcons.push('loli');
      if ($('#hideIconShotaCheckbox').is(':checked')) newHiddenIcons.push('shota');
      if ($('#hideIconGoreDeathCheckbox').is(':checked')) newHiddenIcons.push('goreDeath');
      if ($('#hideIconPregnantCheckbox').is(':checked')) newHiddenIcons.push('pregnant');
      if ($('#hideIconBestialityCheckbox').is(':checked')) newHiddenIcons.push('bestiality');
      if ($('#hideIconFeetCheckbox').is(':checked')) newHiddenIcons.push('feet');
      if ($('#hideIconBondageCheckbox').is(':checked')) newHiddenIcons.push('bondage');
      if ($('#hideIconPoopCheckbox').is(':checked')) newHiddenIcons.push('poop');
      if ($('#hideIconPissCheckbox').is(':checked')) newHiddenIcons.push('piss');
      if ($('#hideIconGroupCheckbox').is(':checked')) newHiddenIcons.push('group');
      if ($('#hideIconIncestCheckbox').is(':checked')) newHiddenIcons.push('incest');
      if ($('#hideIconBukkakeCheckbox').is(':checked')) newHiddenIcons.push('bukkake');
      if ($('#hideIconTentaclesCheckbox').is(':checked')) newHiddenIcons.push('tentacles');
      if ($('#hideIconRapeCheckbox').is(':checked')) newHiddenIcons.push('rape');
      if ($('#hideIconPublicCheckbox').is(':checked')) newHiddenIcons.push('public');
      if ($('#hideIconFurryCheckbox').is(':checked')) newHiddenIcons.push('furry');
      if ($('#hideIconFatCheckbox').is(':checked')) newHiddenIcons.push('fat');
      if ($('#hideIconHypnosisCheckbox').is(':checked')) newHiddenIcons.push('hypnosis');
      if ($('#hideIconNtrCheckbox').is(':checked')) newHiddenIcons.push('ntr');
      if ($('#hideIconFemdomCheckbox').is(':checked')) newHiddenIcons.push('femdom');
      if ($('#hideIconSafeCheckbox').is(':checked')) newHiddenIcons.push('safe');
      if ($('#hideIconQuestionableCheckbox').is(':checked')) newHiddenIcons.push('questionable');
      if ($('#hideIconExplicitCheckbox').is(':checked')) newHiddenIcons.push('explicit');

      GM.setValue('hiddenIcons', newHiddenIcons);

      location.reload();
    }

    // Create the toolbar. Only create if there isn't one already and if there is a image, video or thumbnails.
    if ($('#ibenhancer').length < 1 && ($(containerDOM + ' ' + imageDOM).length || $(containerDOM + ' video').length || $(thumbnailDOM).length)) {
      if (debugMode) console.log('Create toolbar');

      if (placeSettingsAfter)
        $(toolbarDOM).first().after("<div id='ibenhancer'>Image Board Enhancer<br></div>");
      else $(toolbarDOM).first().before("<div id='ibenhancer'>Image Board Enhancer<br></div>");

      if (showFitButton && ($(containerDOM + ' ' + imageDOM).length || $(containerDOM + ' video').length)) {
        $("#ibenhancer").append("<button id='fitContentButton' style='margin-top: 3px;'>Fit</button>");
        $("#fitContentButton").click(function () { getContentProps(); fitContent(0); });
      }

      if (showScrollButton && ($(containerDOM + ' ' + imageDOM).length || $(containerDOM + ' video').length)) {
        $("#ibenhancer").append("<button id='scrollContentButton' style='margin-top: 3px;'>Scroll</button>");
        $("#scrollContentButton").click(scrollToContent);
      }

      // Create settings.
      $("#ibenhancer").append("<br><button id='ibenhancerSettingsButton' style='margin-top: 3px;'>Settings</button>");
      $("#ibenhancerSettingsButton").click(showSettings);
      $("#ibenhancer").append(`
        <div id="ibenhancerSettings-blocker"></div>
        <div id="ibenhancerSettings">
          <div id="ibenhancerSettings-options">
            <label><input id="resizeImageToFitCheckbox" type="checkbox" ` + (resizeImageToFit ? `checked` : ``) + `>Resize images to fit screen.</label>
            <br>
            <label><input id="resizeVideoToFitCheckbox" type="checkbox" ` + (resizeVideoToFit ? `checked` : ``) + `>Resize videos to fit screen.</label>
            <br>
            <label><input id="autoplayVideosCheckbox" type="checkbox" ` + (autoplayVideos ? `checked` : ``) + `>Autoplay videos.</label>
            <br>
            <label><input id="autoScrollToContentCheckbox" type="checkbox" ` + (autoScrollToContent ? `checked` : ``) + `>Scroll to content.</label>
            <br>
            <label><input id="updateWithWindowResizeCheckbox" type="checkbox" ` + (updateWithWindowResize ? `checked` : ``) + `>Resize content with window.</label>
            <br>
            <label><input id="updateScrollOnWindowResizeCheckbox" type="checkbox" ` + (updateScrollOnWindowResize ? `checked` : ``) + `>Scroll to content on window resize.</label>
            <br>
            <label><input id="showFitButtonCheckbox" type="checkbox" ` + (showFitButton ? `checked` : ``) + `>Show fit button.</label>
            <br>
            <label><input id="showScrollButtonCheckbox" type="checkbox" ` + (showScrollButton ? `checked` : ``) + `>Show scroll button.</label>
            <br>
            <label><input id="showVotingButtonsCheckbox" type="checkbox" ` + (showVotingButtons ? `checked` : ``) + `>Show like and favorite buttons.</label>
            <br>
            <label><input id="removeFluidCheckbox" type="checkbox" ` + (removeFluid ? `checked` : ``) + `>Remove fluid video player.</label>
            <br>
            <label><input id="enableEnhancedThumbnailsCheckbox" type="checkbox" ` + (enableEnhancedThumbnails ? `checked` : ``) + `>Enable enhanced thumbnails.</label>
            <br>
            <label><input id="alwaysShowScrollbarsCheckbox" type="checkbox" ` + (alwaysShowScrollbars ? `checked` : ``) + `>Always show scrollbars. (Fixes resize issue.)</label>
            <br>
            <label><input id="enableZoomableImageCheckbox" type="checkbox" ` + (enableZoomableImage ? `checked` : ``) + `>Enable zoomable image.</label>
            <br>
            <label>Max zoom: <input id="maxZoomInput" type="number" min="1" max="5" step="1" value="` + maxZoom + `" style="width:60px;">1 - 5</label>
            <br>
            <label>Zoom speed: <input id="zoomSpeedInput" type="number" min="1" max="15" step="1" value="` + zoomSpeed + `" style="width:60px;">1 - 15</label>
            <br>
            <label>Video volume: <input id="videoVolumeInput" type="number" min="0" max="1" step="0.01" value="` + videoVolume + `" style="width:60px;">0 - 1</label>
            <br>
            <label>Icon Size: <input id="iconSizeInput" type="number" min="16" max="50" step="1" value="` + iconSize + `" style="width:60px;">16 - 50</label>
            <br>
            <label>Resize keyboard shurtcut: <button id="resizeButton">` + resizeButton + `</button></label>
            <br>
            <label>Scroll keyboard shurtcut: <button id="scrollButton">` + scrollButton + `</button></label>
            <br>
            Hide icons: <button id="hideAllIconsButton">Hide All</button> <button id="unhideAllIconsButton">Unhide All</button>
            <br>
            <span id="iconCheckboxes">
              <label><input id="hideIconGifCheckbox" type="checkbox" ` + (hiddenIcons.includes("gif") ? `checked` : ``) + `>GIF</label>
              <label><input id="hideIconVideoCheckbox" type="checkbox" ` + (hiddenIcons.includes("video") ? `checked` : ``) + `>Video</label>
              <label><input id="hideIconSoundCheckbox" type="checkbox" ` + (hiddenIcons.includes("sound") ? `checked` : ``) + `>Sound</label>
              <label><input id="hideIconFlashCheckbox" type="checkbox" ` + (hiddenIcons.includes("flash") ? `checked` : ``) + `>Flash</label>
              <label><input id="hideIconStraightCheckbox" type="checkbox" ` + (hiddenIcons.includes("straight") ? `checked` : ``) + `>Straight</label>
              <label><input id="hideIconGayCheckbox" type="checkbox" ` + (hiddenIcons.includes("gay") ? `checked` : ``) + `>Yaoi/Gay</label>
              <label><input id="hideIconLesbianCheckbox" type="checkbox" ` + (hiddenIcons.includes("lesbian") ? `checked` : ``) + `>Yuri/Lesbian</label>
              <label><input id="hideIconTransCheckbox" type="checkbox" ` + (hiddenIcons.includes("trans") ? `checked` : ``) + `>Futanari/Transsexual</label>
              <label><input id="hideIconTrapCheckbox" type="checkbox" ` + (hiddenIcons.includes("trap") ? `checked` : ``) + `>Trap</label>
              <label><input id="hideIconThreeDCheckbox" type="checkbox" ` + (hiddenIcons.includes("threeD") ? `checked` : ``) + `>3D</label>
              <label><input id="hideIconLoliCheckbox" type="checkbox" ` + (hiddenIcons.includes("loli") ? `checked` : ``) + `>Loli</label>
              <label><input id="hideIconShotaCheckbox" type="checkbox" ` + (hiddenIcons.includes("shota") ? `checked` : ``) + `>Shota</label>
              <label><input id="hideIconGoreDeathCheckbox" type="checkbox" ` + (hiddenIcons.includes("goreDeath") ? `checked` : ``) + `>Gore/Death</label>
              <label><input id="hideIconPregnantCheckbox" type="checkbox" ` + (hiddenIcons.includes("pregnant") ? `checked` : ``) + `>Pregnant</label>
              <label><input id="hideIconBestialityCheckbox" type="checkbox" ` + (hiddenIcons.includes("bestiality") ? `checked` : ``) + `>Bestiality</label>
              <label><input id="hideIconFeetCheckbox" type="checkbox" ` + (hiddenIcons.includes("feet") ? `checked` : ``) + `>Feet/Footjob</label>
              <label><input id="hideIconBondageCheckbox" type="checkbox" ` + (hiddenIcons.includes("bondage") ? `checked` : ``) + `>Bondage/BDSM</label>
              <label><input id="hideIconPoopCheckbox" type="checkbox" ` + (hiddenIcons.includes("poop") ? `checked` : ``) + `>Scat</label>
              <label><input id="hideIconPissCheckbox" type="checkbox" ` + (hiddenIcons.includes("piss") ? `checked` : ``) + `>Piss/Golden Shower</label>
              <label><input id="hideIconGroupCheckbox" type="checkbox" ` + (hiddenIcons.includes("group") ? `checked` : ``) + `>Group Sex/Gangbang</label>
              <label><input id="hideIconIncestCheckbox" type="checkbox" ` + (hiddenIcons.includes("incest") ? `checked` : ``) + `>Incest</label>

              <label><input id="hideIconBukkakeCheckbox" type="checkbox" ` + (hiddenIcons.includes("bukkake") ? `checked` : ``) + `>Bukkake</label>
              <label><input id="hideIconTentaclesCheckbox" type="checkbox" ` + (hiddenIcons.includes("tentacles") ? `checked` : ``) + `>Tentacles</label>
              <label><input id="hideIconRapeCheckbox" type="checkbox" ` + (hiddenIcons.includes("rape") ? `checked` : ``) + `>Rape</label>
              <label><input id="hideIconPublicCheckbox" type="checkbox" ` + (hiddenIcons.includes("public") ? `checked` : ``) + `>Public</label>
              <label><input id="hideIconFurryCheckbox" type="checkbox" ` + (hiddenIcons.includes("furry") ? `checked` : ``) + `>Furry</label>
              <label><input id="hideIconFatCheckbox" type="checkbox" ` + (hiddenIcons.includes("fat") ? `checked` : ``) + `>BBW</label>
              <label><input id="hideIconHypnosisCheckbox" type="checkbox" ` + (hiddenIcons.includes("hypnosis") ? `checked` : ``) + `>Hypnosis</label>
              <label><input id="hideIconNtrCheckbox" type="checkbox" ` + (hiddenIcons.includes("ntr") ? `checked` : ``) + `>NTR</label>
              <label><input id="hideIconFemdomCheckbox" type="checkbox" ` + (hiddenIcons.includes("femdom") ? `checked` : ``) + `>Femdom/Dominatrix</label>


              <label><input id="hideIconSafeCheckbox" type="checkbox" ` + (hiddenIcons.includes("safe") ? `checked` : ``) + `>Rating: Safe</label>
              <label><input id="hideIconQuestionableCheckbox" type="checkbox" ` + (hiddenIcons.includes("questionable") ? `checked` : ``) + `>Rating: Questionable</label>
              <label><input id="hideIconExplicitCheckbox" type="checkbox" ` + (hiddenIcons.includes("explicit") ? `checked` : ``) + `>Rating: Explicit</label>
            </span>
          </div>
          <button id="ibenhancerSettingsSave">Save</button><button id="ibenhancerSettingsCancel">Cancel</button>
        </div>
      ` );

      $("#ibenhancerSettingsSave").click(saveSettings);
      $("#ibenhancerSettingsCancel").click(hideSettings);
      $("#resizeButton").click(changeResizeButtonClicked);
      $("#scrollButton").click(changeScrollButtonClicked);

      $("#hideAllIconsButton").click(() => $('#iconCheckboxes input[type=checkbox]').prop('checked', true));
      $("#unhideAllIconsButton").click(() => $('#iconCheckboxes input[type=checkbox]').prop('checked', false));


      addGlobalStyle(`
        html.ibenhancerSettingVisible {
          overflow: hidden !important;
        }
        #ibenhancer {
          background: white !important;
          color: black !important;
          border: solid 1px grey;
          border-radius: 4px;
          padding: 5px;
          width: 170px;
          text-align: center !important;
          margin-top: 5px;
          margin-bottom: 5px;
          margin-right: auto;
          ` + containerAlignment + `
        }
        #ibenhancer, #ibenhancerSettings label {
          font-size: 15px !important;
          font-family: Arial, Helvetica, sans-serif !important;
          font-style: normal !important;
          font-weight: normal !important;
          color: black;
        }
        #ibenhancerSettings-blocker {
          position: fixed;
          content: '';
          background-color: rgba(0, 0, 0, .5);
          width: 100vw;
          height: 100vh;
          top: 0;
          left: 0;
          z-index: 1;
          display: none;
        }
        #ibenhancerSettings-blocker.show {
          display: block;
        }
        #ibenhancerSettings {
          position: fixed;
          width: 400px;
          height: 400px;
          left: calc(50vw - 155px);
          top: calc(50vh - 165px);
          background-color: white;
          border: 2px solid black;
          border-radius: 3px;
          padding: 10px;
          text-align: left;
          z-index: 999999;
          display: none;
          -webkit-box-sizing: unset;
          -moz-box-sizing: unset;
          box-sizing: unset;
          color: black;
          padding-bottom: 0px;
        }
        #ibenhancerSettings-options {
          overflow-y: auto;
          overflow-x: hidden;
          width: 100%;
          height: calc(100% - 32px);
        }
        #ibenhancerSettings input {
          margin: 5px;
          width: auto;
        }
        #ibenhancerSettings input[type=number] {
          border: solid 1px darkgrey;
        }
        #ibenhancer button {
          padding: 3px !important;
          width: auto;
          border: solid 1px darkgrey !important;
          margin: 2px !important;
          border-radius 2px !important;
          background: WhiteSmoke !important;
          cursor: pointer;
        }
        #ibenhancerSettings.show {
          display: block;
        }
        #fitContentButton {
          width: 73px !important;
        }
        #scrollContentButton {
          width: 73px !important;
        }
        #ibenhancerSettingsButton {
          width: 150px !important;
        }
			`);

      // Add the like and favorite button
      if (showVotingButtons && loggedin && ($(containerDOM + ' ' + imageDOM).length || $(containerDOM + ' video').length)) {
        if (debugMode) console.log('Voting Buttons');

        // All sites handle votes and favorites differently.
        // Some you can like and then remove that like.
        // Others you can like or dislike and remove.
        // Some you can like or dislike and not remove.
        // Some have a score but no like button.
        // Some have a add to favorite button but not a remove. (Remove from a different page.)
        // And then theres konochan and yand.re, that voting system is weird. 0 to 3 stars where 3 stars adds it to you favorites and favoriting something gives it 3 stars then changing your vote removes the favorite.
        // Sankaku has a great system right at the top, so no need to change that.

        // missing: tbib(like), Danbooru(like), rule34.paheal.net(I dont have an account)

        $("#ibenhancer").append('<br>' +
          '<div id="ibenhancer-post-controls">' +

          '<div id="like-button" class="ibenhancer-button" alt="like" tooltip="Like">' +
          likeButtonSvg +
          '</div>' +

          '<div id="dislike-button" class="ibenhancer-button" alt="dislike" tooltip="Dislike">' +
          likeButtonSvg +
          '</div>' +

          '<div id="favorite-button" class="ibenhancer-button" tooltip="Add to Favorites">' +
          favoriteButtonSvg +
          '</div>' +

          '<div id="unfavorite-button" class="ibenhancer-button" tooltip="Remove from Favorites">' +
          favoriteButtonSvg +
          '</div>' +

          '<div id="star0-button" class="ibenhancer-button ibenhancer-star" tooltip="Remove Vote">' +
          undoButtonSvg +
          '</div>' +

          '<div id="star1-button" class="ibenhancer-button ibenhancer-star" tooltip="Vote Good">' +
          starButtonSvg +
          '</div>' +

          '<div id="star2-button" class="ibenhancer-button ibenhancer-star" tooltip="Vote Great">' +
          starButtonSvg +
          '</div>' +

          '<div id="star3-button" class="ibenhancer-button ibenhancer-star" tooltip="Add to Favorites">' +
          starButtonSvg +
          '</div>' +

          '</div>');

        // rule34.xxx
        // no dislike and unfavorite must be done from favorites page
        if (document.location.hostname.toLowerCase() == 'rule34.xxx') {
          $('#ibenhancer-post-controls').addClass('show-like')
          $("#like-button").click(function () { $("#stats > ul > li:contains('(vote up)') > a:contains('up')").click() });
          $('#ibenhancer-post-controls').addClass('show-favorite')
          $("#favorite-button").click(function () { $("#stats + div > ul > li > a:contains('Add to favorites')").click() });
        }

        // gelbooru.com
        // no dislike and unfavorite must be done from favorites page
        else if (document.location.hostname.toLowerCase() == 'gelbooru.com') {
          $('#ibenhancer-post-controls').addClass('show-like')
          $("#like-button").click(function () { $('#container .aside #tag-list a').filter(function (index) { return $(this).text() === "Up"; }).click() });
          $('#ibenhancer-post-controls').addClass('show-favorite')
          $("#favorite-button").click(function () { $('#container .aside #tag-list a').filter(function (index) { return $(this).text() === "Add to favorites"; }).trigger("click") });
        }

        // danbooru.donmai.us
        // no like for dislike butt BUT there is a score
        else if (document.location.hostname.toLowerCase() == 'danbooru.donmai.us') {
          $("#favorite-button").click(function () { $('#add-to-favorites')[0].click(); });
          $("#unfavorite-button").click(function () { $('#remove-from-favorites')[0].click(); });

          function checkAddFavorite() {
            if ($('#add-to-favorites').css('display') != 'none')
              $('#ibenhancer-post-controls').addClass('show-favorite')
            else
              $('#ibenhancer-post-controls').removeClass('show-favorite')
          }
          function checkRemoveFavorite() {
            if ($('#remove-from-favorites').css('display') != 'none')
              $('#ibenhancer-post-controls').addClass('show-unfavorite')
            else
              $('#ibenhancer-post-controls').removeClass('show-unfavorite')
          }


          var observerAddFavorite = new MutationObserver(checkAddFavorite);
          observerAddFavorite.observe(document.getElementById('add-to-favorites'), { attributes: true, attributeFilter: ['style'] });

          var observerRemoveFavorite = new MutationObserver(checkRemoveFavorite);
          observerRemoveFavorite.observe(document.getElementById('remove-from-favorites'), { attributes: true, attributeFilter: ['style'] });

          checkAddFavorite();
          checkRemoveFavorite();
        }

        // konachan.com, konachan.net, yande.re
        // Uses a star rating system from 0 to 3, where 3 adds to your favorites.
        else if (document.location.hostname.toLowerCase() == 'konachan.com' || document.location.hostname.toLowerCase() == 'konachan.net' || document.location.hostname.toLowerCase() == 'yande.re') {
          $('#ibenhancer-post-controls').addClass('show-stars');
          $("#star0-button").click(function () {
            $('.stars.standard-vote-widget .star.star-0')[0].click();
          });
          $("#star1-button").click(function () {
            $('.stars.standard-vote-widget .star.star-1')[0].click();
          });
          $("#star2-button").click(function () {
            $('.stars.standard-vote-widget .star.star-2')[0].click();
          });
          $("#star3-button").click(function () {
            $('.stars.standard-vote-widget .star.star-3')[0].click();
          });
          $('.stars.standard-vote-widget .star.star-1').bind('DOMSubtreeModified', function (e) {
            checkStars('1');
          });
          $('.stars.standard-vote-widget .star.star-2').bind('DOMSubtreeModified', function (e) {
            checkStars('2');
          });
          $('.stars.standard-vote-widget .star.star-3').bind('DOMSubtreeModified', function (e) {
            checkStars('3');
          });
          function checkStars(star) {
            if ($('.stars.standard-vote-widget .star.star-' + star).hasClass('star-set-upto'))
              $("#star" + star + "-button").addClass('star-set-upto');
            else
              $("#star" + star + "-button").removeClass('star-set-upto');
          }
          checkStars('1');
          checkStars('2');
          checkStars('3');
        }

        // safebooru.org
        else if (document.location.hostname.toLowerCase() == 'safebooru.org') {
          $('#ibenhancer-post-controls').addClass('show-favorite')
          $('#ibenhancer-post-controls').addClass('show-like')
          $('#ibenhancer-post-controls').addClass('show-dislike')

          $("#favorite-button").click(function () { $('.sidebar a').filter(function (index) { return $(this).text() === "Add to favorites"; }).click() });
          $("#like-button").click(function () { $('.sidebar a').filter(function (index) { return $(this).text() === "up"; }).click() });
          $("#dislike-button").click(function () { $('.sidebar a').filter(function (index) { return $(this).text() === "down"; }).click() });
        }

        // tbib.org
        else if (document.location.hostname.toLowerCase() == 'tbib.org') {
          $('#ibenhancer-post-controls').addClass('show-favorite')
          $("#favorite-button").click(function () { $('.sidebar a').filter(function (index) { return $(this).text() === "Add to favorites"; }).click() });
        }

        // behoimi.org
        else if (document.location.hostname.toLowerCase() == 'behoimi.org') {
          $('#ibenhancer-post-controls').addClass('show-favorite')
          $('#ibenhancer-post-controls').addClass('show-unfavorite')
          $('#ibenhancer-post-controls').addClass('show-like')
          $('#ibenhancer-post-controls').addClass('show-dislike')

          $("#favorite-button").click(function () { $('#add-to-favs a').click() });
          $("#unfavorite-button").click(function () { $('#remove-from-favs a').click() });
          $("#like-button").click(function () { $('#stats a').filter(function (index) { return $(this).text() === "up"; }).click() });
          $("#dislike-button").click(function () { $('#stats a').filter(function (index) { return $(this).text() === "down"; }).click() });
        }

        // rule34.paheal.net
        else if (document.location.hostname.toLowerCase() == 'rule34.paheal.net') {
          // Can't create an account so I can't do this website
        }

        // rule34hentai.net
        else if (document.location.hostname.toLowerCase() == 'rule34hentai.net') {

          if ($('#Image_Controlsleft input[value="Favorite"]').length > 0)
            $('#ibenhancer-post-controls').addClass('show-favorite')
          if ($('#Image_Controlsleft input[value="Un-Favorite"]').length > 0)
            $('#ibenhancer-post-controls').addClass('show-unfavorite')

          if ($('#Image_Scoreleft input[value="Vote Up"]').length > 0)
            $('#ibenhancer-post-controls').addClass('show-like')



          $("#favorite-button").click(function () { $('#Image_Controlsleft input[value="Favorite"]').click() });
          $("#unfavorite-button").click(function () { $('#Image_Controlsleft input[value="Un-Favorite"]').click() });
          $("#like-button").click(function () { $('#Image_Scoreleft input[value="Vote Up"]').click() });

          // Unused for now.
          var removeLikeRule34hentai = () => $('#Image_Scoreleft input[value="Remove Vote"]').trigger("click");
        }

        // e621.net, e926.net
        else if (document.location.hostname.toLowerCase() == 'e621.net' || document.location.hostname.toLowerCase() == 'e926.net') {

          $('#ibenhancer-post-controls').addClass('e621-vote')

          function checkAddFavorite() {
            if ($('#add-fav-button').css('display') != 'none')
              $('#ibenhancer-post-controls').addClass('show-favorite')
            else
              $('#ibenhancer-post-controls').removeClass('show-favorite')
          }
          function checkRemoveFavorite() {
            if ($('#remove-fav-button').css('display') != 'none')
              $('#ibenhancer-post-controls').addClass('show-unfavorite')
            else
              $('#ibenhancer-post-controls').removeClass('show-unfavorite')
          }

          function checkLiked() {
            console.log('check liked');
            if ($('#image-extra-controls .image-vote-buttons .post-vote-up-link span').hasClass('score-positive')) {
              $("#like-button").addClass('vote-selected')
            } // Set liked style
            else {
              $("#like-button").removeClass('vote-selected')
            } // Remove liked style
          }
          function checkDisliked() {
            if ($('#image-extra-controls .image-vote-buttons .post-vote-down-link span').hasClass('score-negative')) {
              $("#dislike-button").addClass('vote-selected')
            } // Set disliked style
            else {
              $("#dislike-button").removeClass('vote-selected')
            } // Remove disliked style
          }

          var observerAddFavorite = new MutationObserver(checkAddFavorite);
          observerAddFavorite.observe(document.getElementById('add-fav-button'), { attributes: true, attributeFilter: ['style'] });

          var observerRemoveFavorite = new MutationObserver(checkRemoveFavorite);
          observerRemoveFavorite.observe(document.getElementById('remove-fav-button'), { attributes: true, attributeFilter: ['style'] });

          $('#image-extra-controls .image-vote-buttons .post-vote-up-link span').bind('DOMSubtreeModified', checkLiked);
          $('#image-extra-controls .image-vote-buttons .post-vote-down-link span').bind('DOMSubtreeModified', checkDisliked);

          checkAddFavorite();
          checkRemoveFavorite();
          checkLiked();
          checkDisliked();

          $('#ibenhancer-post-controls').addClass('show-like')
          $('#ibenhancer-post-controls').addClass('show-dislike')

          $("#favorite-button").click(function () { $('#image-extra-controls #add-fav-button').click() });
          $("#unfavorite-button").click(function () { $('#image-extra-controls #remove-fav-button').click() });

          $("#like-button").click(function () { $('#image-extra-controls .image-vote-buttons .post-vote-up-link span').click() });
          $("#dislike-button").click(function () { $('#image-extra-controls .image-vote-buttons .post-vote-down-link span').click() });
        }

        addGlobalStyle(`
          #ibenhancer-post-controls {
            display: flex;
            justify-content: center;
          }
          .ibenhancer-button {
            cursor: pointer;
            width: 32px;
            padding: 3px;
            margin: 0;
            border: none;
            vertical-align: middle;
            display: none;
          }
          #favorite-button, #unfavorite-button {
            stroke: #E04F5F;
            stroke-width: 64px;
            fill: transparent;
          }
          #unfavorite-button {
            fill: #E04F5F;
          }
          #like-button {
            fill: #2ECC71;
          }
          #dislike-button {
            fill: #E04F5F;
          }
          #ibenhancer-post-controls.e621-vote #like-button,
          #ibenhancer-post-controls.e621-vote #dislike-button {
            fill: #1F3C67;
          }
          #ibenhancer-post-controls.e621-vote #like-button.vote-selected {
            fill: #2ECC71;
          }
          #ibenhancer-post-controls.e621-vote #dislike-button.vote-selected {
            fill: #E04F5F;
          }
          #dislike-button svg {
            transform: scaleY(-1);
          }
          #star0-button, #star1-button, #star2-button, #star3-button {
            stroke-width: 42px;
            fill: transparent;
          }
          #star0-button {
            fill: black;
          }
          #star1-button {
            stroke: #FCA106;
          }
          #star2-button {
            stroke: #FB6222;
          }
          #star3-button {
            stroke: #E04F5F;
          }
          #star1-button.star-set-upto {
            fill: #FCA106;
          }
          #star2-button.star-set-upto {
            fill: #FB6222;
          }
          #star3-button.star-set-upto {
            fill: #E04F5F;
          }
          .ibenhancer-button:hover {
            background-color: rgba(255,255,255,.5);
          }
          .ibenhancer-button:active {
            background-color: rgba(255,255,255,1);
          }
          #ibenhancer-post-controls.show-like #like-button,
          #ibenhancer-post-controls.show-dislike #dislike-button,
          #ibenhancer-post-controls.show-favorite #favorite-button,
          #ibenhancer-post-controls.show-unfavorite #unfavorite-button,
          #ibenhancer-post-controls.show-stars .ibenhancer-star {
            display: block;
          }
			  `);

        // Add CSS tooltip support.
        addGlobalStyle(`
          [tooltip] {
            position: relative;
          }
          
          [tooltip]:after,
          [tooltip-left]:after,
          [tooltip-right]:after {
            position        : absolute;
            color           : #FFF;
            background-color: #232F34BB;
            border-radius   : 0.25rem;
            padding         : .5rem;
            white-space     : nowrap;
            display         : none;
            font-size       : .8rem;
          }
          
          [tooltip]:after {
            content  : attr(tooltip);
            right    : initial;
            left     : 50%;
            top      : 100%;
            transform: translate(-50%, .5rem);
          }
          
          
          [tooltip-left]:after {
            content  : attr(tooltip-left);
            left     : initial;
            right    : calc(100%);
            top      : 50%;
            transform: translate(-0.5rem, -50%);
          }
          
          [tooltip-right].right:after {
            content  : attr(tooltip-right);
            left     : calc(100%);
            right    : initial;
            top      : 50%;
            transform: translate(.5rem, -50%);
          }
          
          [tooltip]:hover:after,
          [tooltip-left]:hover:after,
          [tooltip-right]:hover:after {
            display : block;
            position: absolute;
          }
        `);
      }
    }

    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);
    }

    // Keyboard shortcuts
    document.addEventListener('keyup', (e) => {
      if (debugMode) console.log(e.code)
      if (!changeKeyboardShortcut) {
        if (e.code === resizeButton) { getContentProps(0); fitContent(0); }
        else if (e.code === scrollButton) scrollToContent(0);
      }
      else if (changeKeyboardShortcut == 'resizeButton') {
        resizeButton = e.code;
        $('#resizeButton').html(e.code);
        changeKeyboardShortcut = false;
      }
      else if (changeKeyboardShortcut == 'scrollButton') {
        scrollButton = e.code;
        $('#scrollButton').html(e.code);
        changeKeyboardShortcut = false;
      }
    });

    if (urlParams.get('page') && urlParams.get('page').toLowerCase() == 'favorites') unsupportedThumbnailPage = true; // Add method to remove favorite.

    // Get Thumbnails
    if (enableEnhancedThumbnails) thumbnails = $(thumbnailDOM);

    function checkForMoreThumbnails() {
      var oldNumber = thumbnails.length;
      thumbnails = $(thumbnailDOM);
      return (thumbnails.length > oldNumber);
    }

    if (!unsupportedThumbnailPage && thumbnails.length > 0) {
      $('body').append(`
        <a href="#" id="thumbPlusPreviewLink" style="">
          <div id="thumbPlusPreview" class="">
            <div id="thumbPlusPreviewImage"></div>
            <div id="thumbPlusIcons" style="position: relative;">
              <span id="thumbPlusPreviewGif" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("gif") ? `` : `show`) + `" title="GIF">` + icons['gif'] + `</span>
              <span id="thumbPlusPreviewVideo" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("video") ? `` : `show`) + `" title="Video">` + icons['video'] + `</span>
              <span id="thumbPlusPreviewFlash" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("flash") ? `` : `show`) + `" title="Flash Animation">` + icons['flash'] + `</span>
              <span id="thumbPlusPreviewSound" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("sound") ? `` : `show`) + `" title="Has Sound">` + icons['sound'] + `</span>
              <span id="thumbPlusPreview3D" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("threeD") ? `` : `show`) + `" title="3D">` + icons['threeD'] + `</span>
              <span id="thumbPlusPreviewStraight" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("straight") ? `` : `show`) + `" title="Straight">` + icons['straight'] + `</span>
              <span id="thumbPlusPreviewGay" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("gay") ? `` : `show`) + `" title="Yaoi/Gay">` + icons['gay'] + `</span>
              <span id="thumbPlusPreviewLesbian" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("lesbian") ? `` : `show`) + `" title="Yuri/Lesbian">` + icons['lesbian'] + `</span>
              <span id="thumbPlusPreviewTrans" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("trans") ? `` : `show`) + `" title="Futanari/Transsexual">` + icons['trans'] + `</span>
              <span id="thumbPlusPreviewTrap" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("trap") ? `` : `show`) + `" title="Trap">` + icons['trap'] + `</span>
              <span id="thumbPlusPreviewLoli" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("loli") ? `` : `show`) + `" title="Loli">` + icons['loli'] + `</span>
              <span id="thumbPlusPreviewShota" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("shota") ? `` : `show`) + `" title="Shota">` + icons['shota'] + `</span>
              <span id="thumbPlusPreviewGoreDeath" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("goreDeath") ? `` : `show`) + `" title="Gore/Death">` + icons['goreDeath'] + `</span>
              <span id="thumbPlusPreviewPregnant" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("pregnant") ? `` : `show`) + `" title="Pregnant">` + icons['pregnant'] + `</span>
              <span id="thumbPlusPreviewBestiality" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("bestiality") ? `` : `show`) + `" title="Bestiality">` + icons['bestiality'] + `</span>
              <span id="thumbPlusPreviewFeet" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("feet") ? `` : `show`) + `" title="Feet/Footjob">` + icons['feet'] + `</span>
              <span id="thumbPlusPreviewBondage" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("bondage") ? `` : `show`) + `" title="Bondage/BDSM">` + icons['bondage'] + `</span>
              <span id="thumbPlusPreviewPoop" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("poop") ? `` : `show`) + `" title="Scat">` + icons['poop'] + `</span>
              <span id="thumbPlusPreviewPiss" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("piss") ? `` : `show`) + `" title="Piss/Golden Shower">` + icons['piss'] + `</span>
              <span id="thumbPlusPreviewGroup" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("group") ? `` : `show`) + `" title="Group Sex/Gangbang">` + icons['group'] + `</span>
              <span id="thumbPlusPreviewIncest" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("incest") ? `` : `show`) + `" title="Incest">` + icons['incest'] + `</span>
              <span id="thumbPlusPreviewBukkake" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("bukkake") ? `` : `show`) + `" title="Bukkake">` + icons['bukkake'] + `</span>
              <span id="thumbPlusPreviewTentacles" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("tentacles") ? `` : `show`) + `" title="Tentacles">` + icons['tentacles'] + `</span>
              <span id="thumbPlusPreviewRape" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("rape") ? `` : `show`) + `" title="Rape">` + icons['rape'] + `</span>
              <span id="thumbPlusPreviewPublic" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("public") ? `` : `show`) + `" title="Public Sex/Exhibitionism">` + icons['public'] + `</span>
              <span id="thumbPlusPreviewFurry" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("furry") ? `` : `show`) + `" title="Furry">` + icons['furry'] + `</span>
              <span id="thumbPlusPreviewFat" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("fat") ? `` : `show`) + `" title="Chubby/BBW">` + icons['fat'] + `</span>
              <span id="thumbPlusPreviewHypnosis" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("hypnosis") ? `` : `show`) + `" title="Hypnosis/Mind Control">` + icons['hypnosis'] + `</span>
              <span id="thumbPlusPreviewNtr" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("ntr") ? `` : `show`) + `" title="Netorare (NTR)/Cuckold">` + icons['ntr'] + `</span>
              <span id="thumbPlusPreviewFemdom" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("femdom") ? `` : `show`) + `" title="Femdom">` + icons['femdom'] + `</span>
              <span id="thumbPlusPreviewSafe" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("safe") ? `` : `show`) + `" title="Rating: Safe">` + icons['safe'] + `</span>
              <span id="thumbPlusPreviewQuestionable" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("questionable") ? `` : `show`) + `" title="Rating: Questionable">` + icons['questionable'] + `</span>
              <span id="thumbPlusPreviewExplicit" class="thumbPlusPreviewIcon ` + (hiddenIcons.includes("explicit") ? `` : `show`) + `" title="Rating: Explicit">` + icons['explicit'] + `</span>
            </div>
          </div>
        </a>
      `);
      $('#thumbPlusPreview').css({ backgroundColor: $('body').css("background-color") != "rgba(0, 0, 0, 0)" ? $('body').css("background-color") : 'white' });
      $('#thumbPlusPreviewContextMenuRemoveFavorite').click(function () { alert('Clicked') });
      $('#thumbPlusPreview').mouseout(function () {
        if (!debugMode || (!keepThumbOpen && debugMode)) {
          $('#thumbPlusPreviewLink').removeClass('show');
          $('#thumbPlusPreview').removeClass('show gif video sound flash straight gay lesbian trans threed trap loli shota gore pregnant bestiality feet bondage poop piss group incest bukkake tentacles rape public furry fat hypnosis ntr femdom safe questionable explicit');
        }
      })

      function addThumbnailEnhancement() {
        if (debugMode) console.log('Add thumbnails');
        if (enableEnhancedThumbnails) thumbnails = $(thumbnailDOM);

        var tmp = 0;
        thumbnails.each(function () {
          if (!$(this).hasClass('ibeThumbnail')) {
            $(this).mouseover(function (e) {
              thumbnailMouseOver(this);
            })
            $(this).addClass('ibeThumbnail');
            tmp++;
          }
        });
        console.log('Added', tmp, 'thumbnails.');
      }

      addThumbnailEnhancement();
      setInterval(function () {
        if (checkForMoreThumbnails()) addThumbnailEnhancement()
      }, 100);

      function thumbnailMouseOver(thumb) {

        if ($('img', thumb).attr('oldtitle') && $('img', thumb).attr('oldtitle') != '') // oldtitle is used for gelbooru
          var title = $('img', thumb).attr('oldtitle');
        else
          var title = $('img', thumb).attr('title');

        var tags = title.split(' ');

        if ($('img', thumb).attr('rating')) tags.push($('img', thumb).attr('rating'));

        for (let i = 0; i < tags.length; i++) {
          tags[i] = tags[i].toLowerCase().split(',').join('');
        }

        if (tags.includes("webm")) $('#thumbPlusPreview').addClass('video');
        else if (tags.includes("mp4")) $('#thumbPlusPreview').addClass('video');
        else if (tags.includes("animated_gif")) $('#thumbPlusPreview').addClass('gif');
        else if (tags.includes("flash")) $('#thumbPlusPreview').addClass('flash');
        else if (tags.includes("flash_animation")) $('#thumbPlusPreview').addClass('flash');
        else if (tags.includes("video")) $('#thumbPlusPreview').addClass('video');
        else if (tags.includes("animated") && animationTagIsGif && !tags.includes("sound")) $('#thumbPlusPreview').addClass('gif');
        else if (tags.includes("animated")) $('#thumbPlusPreview').addClass('video');

        if (tags.includes("sound")) $('#thumbPlusPreview').addClass('sound');
        else if (tags.includes("audio")) $('#thumbPlusPreview').addClass('sound');
        else if (tags.includes("has_sound")) $('#thumbPlusPreview').addClass('sound');
        else if (tags.includes("has_audio")) $('#thumbPlusPreview').addClass('sound');
        else if (tags.includes("video_with_sound")) $('#thumbPlusPreview').addClass('sound');

        if (tags.includes("hetero")) $('#thumbPlusPreview').addClass('straight');
        else if (tags.includes("straight")) $('#thumbPlusPreview').addClass('straight');
        else if (tags.includes("male/female")) $('#thumbPlusPreview').addClass('straight');

        if (tags.includes("yaoi")) $('#thumbPlusPreview').addClass('gay');
        else if (tags.includes("gay")) $('#thumbPlusPreview').addClass('gay');
        else if (tags.includes("male/male")) $('#thumbPlusPreview').addClass('gay');

        if (tags.includes("yuri")) $('#thumbPlusPreview').addClass('lesbian');
        else if (tags.includes("lesbian")) $('#thumbPlusPreview').addClass('lesbian');
        else if (tags.includes("female/female")) $('#thumbPlusPreview').addClass('lesbian');

        if (tags.includes("intersex")) $('#thumbPlusPreview').addClass('trans')
        else if (tags.includes("futanari")) $('#thumbPlusPreview').addClass('trans');
        else if (tags.includes("newhalf")) $('#thumbPlusPreview').addClass('trans');
        else if (tags.includes("dickgirl")) $('#thumbPlusPreview').addClass('trans');
        else if (tags.includes("shemale")) $('#thumbPlusPreview').addClass('trans');

        if (tags.includes("trap")) $('#thumbPlusPreview').addClass('trap');
        else if (tags.includes("otoko_no_ko")) $('#thumbPlusPreview').addClass('trap');

        if (tags.includes("3d")) $('#thumbPlusPreview').addClass('threed');

        if (tags.includes("loli")) $('#thumbPlusPreview').addClass('loli');

        if (tags.includes("shota")) $('#thumbPlusPreview').addClass('shota');

        if (tags.includes("guro")) $('#thumbPlusPreview').addClass('gore');
        else if (tags.includes("gore")) $('#thumbPlusPreview').addClass('gore');
        else if (tags.includes("death")) $('#thumbPlusPreview').addClass('gore');
        else if (tags.includes("snuf")) $('#thumbPlusPreview').addClass('gore');

        if (tags.includes("pregnant")) $('#thumbPlusPreview').addClass('pregnant');
        else if (tags.includes("pregnant_futa")) $('#thumbPlusPreview').addClass('pregnant');
        else if (tags.includes("pregnant_loli")) $('#thumbPlusPreview').addClass('pregnant');

        if (tags.includes("bestiality")) $('#thumbPlusPreview').addClass('bestiality');
        else if (tags.includes("zoophilia")) $('#thumbPlusPreview').addClass('bestiality');

        // A lot seem to be tagged with feet when it is not the main focus and many foot fetish posts are only tagged as feet.
        // if (tags.includes("feet")) $('#thumbPlusPreview').addClass('feet');
        // else
        if (tags.includes("ashikoki")) $('#thumbPlusPreview').addClass('feet');
        else if (tags.includes("footjob")) $('#thumbPlusPreview').addClass('feet');
        else if (tags.includes("foot_fetish")) $('#thumbPlusPreview').addClass('feet');
        else if (tags.includes("foot_focus")) $('#thumbPlusPreview').addClass('feet');
        else if (tags.includes("foot_worship")) $('#thumbPlusPreview').addClass('feet');
        else if (tags.includes("pov_feet")) $('#thumbPlusPreview').addClass('feet');


        if (tags.includes("bondage")) $('#thumbPlusPreview').addClass('bondage');
        else if (tags.includes("bdsm")) $('#thumbPlusPreview').addClass('bondage');

        if (tags.includes("scat")) $('#thumbPlusPreview').addClass('poop');
        else if (tags.includes("defecating")) $('#thumbPlusPreview').addClass('poop');
        else if (tags.includes("feces")) $('#thumbPlusPreview').addClass('poop');
        else if (tags.includes("coprophagia")) $('#thumbPlusPreview').addClass('poop');
        else if (tags.includes("soiling")) $('#thumbPlusPreview').addClass('poop');

        if (tags.includes("urine")) $('#thumbPlusPreview').addClass('piss');
        else if (tags.includes("urinating")) $('#thumbPlusPreview').addClass('piss');
        else if (tags.includes("peeing")) $('#thumbPlusPreview').addClass('piss');
        else if (tags.includes("golden_shower")) $('#thumbPlusPreview').addClass('piss');
        else if (tags.includes("watersports")) $('#thumbPlusPreview').addClass('piss');

        if (tags.includes("group_sex")) $('#thumbPlusPreview').addClass('group');
        else if (tags.includes("gangbang")) $('#thumbPlusPreview').addClass('group');
        else if (tags.includes("threesome")) $('#thumbPlusPreview').addClass('group');
        else if (tags.includes("orgy")) $('#thumbPlusPreview').addClass('group');
        else if (tags.includes("foursome")) $('#thumbPlusPreview').addClass('group');

        if (tags.includes("incest")) $('#thumbPlusPreview').addClass('incest');

        if (tags.includes("bukkake")) $('#thumbPlusPreview').addClass('bukkake');

        if (tags.includes("tentacles")) $('#thumbPlusPreview').addClass('tentacles');
        else if (tags.includes("tentacle")) $('#thumbPlusPreview').addClass('tentacles');
        else if (tags.includes("tentacle_sex")) $('#thumbPlusPreview').addClass('tentacles');

        if (tags.includes("rape")) $('#thumbPlusPreview').addClass('rape');

        if (tags.includes("exhibitionism")) $('#thumbPlusPreview').addClass('public');
        else if (tags.includes("public_nudity")) $('#thumbPlusPreview').addClass('public');
        else if (tags.includes("public_sex")) $('#thumbPlusPreview').addClass('public');
        else if (tags.includes("public_masturbation")) $('#thumbPlusPreview').addClass('public');
        else if (tags.includes("public_display")) $('#thumbPlusPreview').addClass('public');
        else if (tags.includes("public") && (tags.includes("sex") || tags.includes("nude"))) $('#thumbPlusPreview').addClass('public');

        if (tags.includes("furry")) $('#thumbPlusPreview').addClass('furry');
        else if (tags.includes("anthro")) $('#thumbPlusPreview').addClass('furry');

        if (tags.includes("bbw")) $('#thumbPlusPreview').addClass('fat');
        else if (tags.includes("ssbbw")) $('#thumbPlusPreview').addClass('fat');
        else if (tags.includes("chubby")) $('#thumbPlusPreview').addClass('fat');
        else if (tags.includes("obese")) $('#thumbPlusPreview').addClass('fat');
        else if (tags.includes("overweight")) $('#thumbPlusPreview').addClass('fat');

        if (tags.includes("hypnosis")) $('#thumbPlusPreview').addClass('hypnosis');
        else if (tags.includes("mind_control")) $('#thumbPlusPreview').addClass('hypnosis');

        if (tags.includes("ntr")) $('#thumbPlusPreview').addClass('ntr');
        else if (tags.includes("netorare")) $('#thumbPlusPreview').addClass('ntr');
        else if (tags.includes("cuckold")) $('#thumbPlusPreview').addClass('ntr');

        if (tags.includes("femdom")) $('#thumbPlusPreview').addClass('femdom');
        else if (tags.includes("dominatrix")) $('#thumbPlusPreview').addClass('femdom');

        if (tags.includes("rating:safe")) $('#thumbPlusPreview').addClass('safe');
        else if (tags.includes("safe")) $('#thumbPlusPreview').addClass('safe');
        else if (tags.includes("rating:questionable")) $('#thumbPlusPreview').addClass('questionable');
        else if (tags.includes("questionable")) $('#thumbPlusPreview').addClass('questionable');
        else if (tags.includes("rating:explicit")) $('#thumbPlusPreview').addClass('explicit');
        else if (tags.includes("explicit")) $('#thumbPlusPreview').addClass('explicit');

        $('#thumbPlusPreviewLink').css({ top: cumulativeOffset(thumb).top, left: cumulativeOffset(thumb).left });
        $('#thumbPlusPreviewImage').css({ backgroundImage: 'url(' + $('img', thumb).attr('src') + ')' });
        $('#thumbPlusPreviewImage').attr('title', title);

        var height = $('img', thumb).height() * 1.555;
        if (height) $('#thumbPlusPreviewImage').css({ height: $('img', thumb).height() * 1.555 });

        if ($(thumb).attr('href'))
          $('#thumbPlusPreviewLink').attr('href', $(thumb).attr('href'));
        else
          $('#thumbPlusPreviewLink').attr('href', $('a', thumb).attr('href'));

        $('#thumbPlusPreviewLink').addClass('show');
      }
      addGlobalStyle(`
        #thumbPlusPreviewLink {
          background-color: white;
          position: absolute;
          top: 0px;
          left: 0px;
          display: none;
          z-index: 999999;
        }
        #thumbPlusPreviewLink.show {
          display: block;
        }
        #thumbPlusPreview {
          display: flex;
          top: 0;
          left: 0;
          border: 2px solid black;
          border-radius: 5px;
          flex-direction: column !important;
          align-content: center !important;
          justify-content: center !important;
          align-items: center !important;
          flex-grow: 4 !important; 
          margin-left: -50px;
          margin-top: -50px;
          width: 280px;
          min-height: 280px;
          max-height: 380px;
        }
        #thumbPlusPreviewImage {
          width: calc(100% * 0.833);
          height: calc(100% * 0.833);
          margin-left: auto;
          margin-right: auto;
          background-repeat: no-repeat;
          background-position: center top;
          background-size: contain;
        }
        #thumbPlusIcons {
          display: flex;
          flex-wrap: wrap;
          justify-content: center;
          margin-top: 4px;
        }
        .thumbPlusPreviewIcon {
          display: none;
          margin: 2px;
          background-color: #fff5;
          border-radius: 3px;
          padding: 0px;
        }
        .thumbPlusPreviewIcon svg {
          border: none;
          vertical-align: middle;
        }
        .thumbPlusPreviewIcon, .thumbPlusPreviewIcon svg {
          width: ` + iconSize + `px;
          height: ` + iconSize + `px;
        }
        #thumbPlusPreview.gif #thumbPlusPreviewGif.show,
        #thumbPlusPreview.video #thumbPlusPreviewVideo.show,
        #thumbPlusPreview.sound #thumbPlusPreviewSound.show,
        #thumbPlusPreview.flash #thumbPlusPreviewFlash.show,
        #thumbPlusPreview.straight #thumbPlusPreviewStraight.show,
        #thumbPlusPreview.gay #thumbPlusPreviewGay.show,
        #thumbPlusPreview.lesbian #thumbPlusPreviewLesbian.show,
        #thumbPlusPreview.trans #thumbPlusPreviewTrans.show,
        #thumbPlusPreview.trap #thumbPlusPreviewTrap.show,
        #thumbPlusPreview.threed #thumbPlusPreview3D.show,
        #thumbPlusPreview.loli #thumbPlusPreviewLoli.show,
        #thumbPlusPreview.shota #thumbPlusPreviewShota.show,
        #thumbPlusPreview.gore #thumbPlusPreviewGoreDeath.show,
        #thumbPlusPreview.pregnant #thumbPlusPreviewPregnant.show,
        #thumbPlusPreview.bestiality #thumbPlusPreviewBestiality.show,
        #thumbPlusPreview.feet #thumbPlusPreviewFeet.show,
        #thumbPlusPreview.bondage #thumbPlusPreviewBondage.show,
        #thumbPlusPreview.poop #thumbPlusPreviewPoop.show,
        #thumbPlusPreview.piss #thumbPlusPreviewPiss.show,
        #thumbPlusPreview.group #thumbPlusPreviewGroup.show,
        #thumbPlusPreview.incest #thumbPlusPreviewIncest.show,
        #thumbPlusPreview.bukkake #thumbPlusPreviewBukkake.show,
        #thumbPlusPreview.tentacles #thumbPlusPreviewTentacles.show,
        #thumbPlusPreview.rape #thumbPlusPreviewRape.show,
        #thumbPlusPreview.public #thumbPlusPreviewPublic.show,
        #thumbPlusPreview.furry #thumbPlusPreviewFurry.show,
        #thumbPlusPreview.fat #thumbPlusPreviewFat.show,
        #thumbPlusPreview.hypnosis #thumbPlusPreviewHypnosis.show,
        #thumbPlusPreview.ntr #thumbPlusPreviewNtr.show,
        #thumbPlusPreview.femdom #thumbPlusPreviewFemdom.show,
        #thumbPlusPreview.safe #thumbPlusPreviewSafe.show,
        #thumbPlusPreview.questionable #thumbPlusPreviewQuestionable.show,
        #thumbPlusPreview.explicit #thumbPlusPreviewExplicit.show {
          display: inline-block;
        }
	    `);
    }

    function closeZoom() {
      $("#IBEZoomableImageContainer").remove();
      if (alwaysShowScrollbars)
        $("html").css({ overflowX: 'scroll', overflowY: 'scroll' });
      else
        $("html").css({ overflowX: 'auto', overflowY: 'auto' });
    }

    function openZoom() {
      addZoomable();
      $("html").css({ overflowX: 'hidden', overflowY: 'hidden' });
    }

    function addZoomable() {
      if ($(containerDOM + ' ' + imageDOM)[0].tagName == "IMG") {
        $('body').append(`
          <div id="IBEZoomableImageContainer" class="show">
            <div id="IBEZoomableImage">
              <div id="IBEZoomableContent">
                <img src="` + $(containerDOM + ' ' + imageDOM).attr('src') + `"/>
              </div>
            </div>
            <div id="IBEZoomableImageClose"><svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewBox="0 0 24 24"><path d="M24 20.188l-8.315-8.209 8.2-8.282-3.697-3.697-8.212 8.318-8.31-8.203-3.666 3.666 8.321 8.24-8.206 8.313 3.666 3.666 8.237-8.318 8.285 8.203z"/></svg></div>
          </div>
        `);
        $("#IBEZoomableImageClose").click(function () { history.back(); });
        $('#IBEZoomableContent img').on('load', function () {
          if (wzoom) setTimeout(function () {
            getWindowProps();
            $('#IBEZoomableContent').css({ width: contentTrueWidth + 'px', height: contentTrueHeight + 'px' });
            wzoom.prepare();
          }, 0);
        });
        addGlobalStyle(` 
          #IBEZoomableImageContainer {
            position: fixed;
            margin: 0px;
            width: 100vw;
            height: 100vh;
            left: 0px;
            top: 0px;
            background-color: #0009;
            z-index: 999999;
            display: none;
          }
          #IBEZoomableImageContainer.show {
            display: block;
          }
          #IBEZoomableImage {
            position: absolute;
            width: 100%;
            height: 100%;
            background-color:blue;
            cursor: grab;
            display: flex;
            align-items: center;
            justify-content: center;
            position: absolute;
            top: 0;
            bottom: 0;
            left: 0;
            width: 100%;
            height: 100%;
            border: 0;
            background-color: gray;
            overflow: hidden;
          }
          #IBEZoomableContent {
            //width: `+ contentTrueWidth + `px;
            //height: `+ contentTrueHeight + `px;
          }
          #IBEZoomableImageContainer img {
            display: block;
            height: auto;
            margin: auto;
        }
          #IBEZoomableImageClose {
            position: absolute;
            width: 30px;
            height: 30px;
            background-color: #0005;
            color: white;
            cursor: pointer;
            fill: white;
          }
          #IBEZoomableImageClose:hover {
            background-color: black;
          }
          #IBEZoomableImageClose svg {
            margin: 5px;
          }
        `);

        var imageElement = document.getElementById('IBEZoomableContent').querySelector('img');

        if (imageElement.complete) {
          init();
        } else {
          imageElement.onload = init;
        }

        function init() {
          var maxScale = parseInt(maxZoom);
          wzoom = WZoom.create('#IBEZoomableContent', {
            type: 'html',
            width: imageElement.naturalWidth,
            height: imageElement.naturalHeight,
            maxScale: maxScale,
            speed: zoomSpeed,
            dragScrollableOptions: {
              onGrab: function () {
                document.getElementById('IBEZoomableImage').style.cursor = 'grabbing';
              },
              onDrop: function () {
                document.getElementById('IBEZoomableImage').style.cursor = 'grab';
              }
            }
          });

          window.addEventListener('resize', function () {
            wzoom.prepare();
          });

        }

      }
    }

    if (enableZoomableImage && $(containerDOM + ' ' + imageDOM).length && !$(containerDOM + ' video').length) {

      window.addEventListener('popstate', function (event) {
        if (event.state && event.state.id && event.state.id == 'default') closeZoom();
        else if (event.state && event.state.id && event.state.id == 'zoom') openZoom();
      });



      $(containerDOM + ' ' + imageDOM).click(function () {
        var currentSrc = $(containerDOM + ' ' + imageDOM).attr('src');
        history.replaceState({ id: "default" }, 'title');
        history.pushState({ id: "zoom" }, '');

        setTimeout(function () {
          if (currentSrc == $(containerDOM + ' ' + imageDOM).attr('src')) openZoom();
          else {
            waitingForZoom = true;
          }
        }, 0)
      })

    }

    var cumulativeOffset = function (element) {
      var top = 0, left = 0;
      do {
        top += element.offsetTop || 0;
        left += element.offsetLeft || 0;
        element = element.offsetParent;
      } while (element);

      return {
        top: top,
        left: left
      };
    };

  }
  catch (e) {
    console.error(e);
  }
  if (debugMode) console.log('End of script.');
})();