Make thumbnails zoom on mouse hover
// ==UserScript== // @name Chaturbate Thumbnails Zoom // @author nima-r // @namespace https://greasyfork.org/en/users/846327-nima-rahbar // @icon https://www.google.com/s2/favicons?sz=64&domain=chaturbate.org // @description Make thumbnails zoom on mouse hover // @copyright 2022, nima-r (https://greasyfork.org/en/users/846327-nima-rahbar) // @license MIT // @version 1.2.7 // @homepageURL https://greasyfork.org/en/scripts/437111-chaturbate-animate-thumbnail-re-layout // @homepage https://greasyfork.org/en/scripts/437111-chaturbate-animate-thumbnail-re-layout // @supportURL https://greasyfork.org/en/scripts/437111-chaturbate-animate-thumbnail-re-layout/feedback // @require https://cdn.jsdelivr.net/npm/[email protected] // @require https://cdn.jsdelivr.net/npm/@violentmonkey/[email protected] // @match *://*.chaturbate.com/* // @run-at document-idle // ==/UserScript== /* global $, VM */ // Immediately Invoked Function Expression (IIFE) to avoid polluting the global scope (() => { // Create a <style> element to hold custom CSS rules const style = document.createElement('style'); // Define your CSS rules for the enlargement button const css = ` .HeaderNavBar .HeaderNavBar__link.enlargementBtn { display: inline-block; width: 20px; height: auto; background-position: center; background-repeat: no-repeat; background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NDAgNjQwIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDcuMi4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjYgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTQwOCA2NEw1NTIgNjRDNTY1LjMgNjQgNTc2IDc0LjcgNTc2IDg4TDU3NiAyMzJDNTc2IDI0MS43IDU3MC4yIDI1MC41IDU2MS4yIDI1NC4yQzU1Mi4yIDI1Ny45IDU0MS45IDI1NS45IDUzNSAyNDlMNDk2IDIxMEw0MDkgMjk3QzM5OS42IDMwNi40IDM4NC40IDMwNi40IDM3NS4xIDI5N0wzNDMuMSAyNjVDMzMzLjcgMjU1LjYgMzMzLjcgMjQwLjQgMzQzLjEgMjMxLjFMNDMwLjEgMTQ0LjFMMzkxLjEgMTA1LjFDMzg0LjIgOTguMiAzODIuMiA4Ny45IDM4NS45IDc4LjlDMzg5LjYgNjkuOSAzOTguMyA2NCA0MDggNjR6TTIzMiA1NzZMODggNTc2Qzc0LjcgNTc2IDY0IDU2NS4zIDY0IDU1Mkw2NCA0MDhDNjQgMzk4LjMgNjkuOCAzODkuNSA3OC44IDM4NS44Qzg3LjggMzgyLjEgOTguMSAzODQuMiAxMDUgMzkxTDE0NCA0MzBMMjMxIDM0M0MyNDAuNCAzMzMuNiAyNTUuNiAzMzMuNiAyNjQuOSAzNDNMMjk2LjkgMzc1QzMwNi4zIDM4NC40IDMwNi4zIDM5OS42IDI5Ni45IDQwOC45TDIwOS45IDQ5NS45TDI0OC45IDUzNC45QzI1NS44IDU0MS44IDI1Ny44IDU1Mi4xIDI1NC4xIDU2MS4xQzI1MC40IDU3MC4xIDI0MS43IDU3NiAyMzIgNTc2eiIvPjwvc3ZnPg=="); } .enlargementBtn.off { background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NDAgNjQwIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDcuMi4wIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjYgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTUwMy41IDcxQzUxMi45IDYxLjYgNTI4LjEgNjEuNiA1MzcuNCA3MUw1NjkuNCAxMDNDNTc4LjggMTEyLjQgNTc4LjggMTI3LjYgNTY5LjQgMTM2LjlMNDgyLjQgMjIzLjlMNTIxLjQgMjYyLjlDNTI4LjMgMjY5LjggNTMwLjMgMjgwLjEgNTI2LjYgMjg5LjFDNTIyLjkgMjk4LjEgNTE0LjIgMzA0IDUwNC41IDMwNEwzNjAuNSAzMDRDMzQ3LjIgMzA0IDMzNi41IDI5My4zIDMzNi41IDI4MEwzMzYuNSAxMzZDMzM2LjUgMTI2LjMgMzQyLjMgMTE3LjUgMzUxLjMgMTEzLjhDMzYwLjMgMTEwLjEgMzcwLjYgMTEyLjEgMzc3LjUgMTE5TDQxNi41IDE1OEw1MDMuNSA3MXpNMTM2LjUgMzM2TDI4MC41IDMzNkMyOTMuOCAzMzYgMzA0LjUgMzQ2LjcgMzA0LjUgMzYwTDMwNC41IDUwNEMzMDQuNSA1MTMuNyAyOTguNyA1MjIuNSAyODkuNyA1MjYuMkMyODAuNyA1MjkuOSAyNzAuNCA1MjcuOSAyNjMuNSA1MjFMMjI0LjUgNDgyTDEzNy41IDU2OUMxMjguMSA1NzguNCAxMTIuOSA1NzguNCAxMDMuNiA1NjlMNzEuNiA1MzdDNjIuMiA1MjcuNiA2Mi4yIDUxMi40IDcxLjYgNTAzLjFMMTU4LjYgNDE2LjFMMTE5LjYgMzc3LjFDMTEyLjcgMzcwLjIgMTEwLjcgMzU5LjkgMTE0LjQgMzUwLjlDMTE4LjEgMzQxLjkgMTI2LjggMzM2IDEzNi41IDMzNnoiLz48L3N2Zz4="); } `; // Set the innerHTML of the <style> element to the defined CSS rules style.innerHTML = css; // Append the <style> element to the <head> of the document to apply the styles document.head.appendChild(style); // Retrieve the enlargement state from localStorage or set it to "on" if not found var enlargement = localStorage.getItem('enlargement') || localStorage.setItem('enlargement', "on"); // When the document is ready $(document).ready(function () { // Add the enlargement button to the navigation bar after the "broadcast yourself" link $(".HeaderNavBar .HeaderNavBar__link").last().after( // Create the button with the current enlargement state `<a href="#" class="HeaderNavBar__link enlargementBtn ${enlargement}"></a>` ); }); // Event handler for click events on the enlargement button $("body").on("click", ".enlargementBtn", function (e) { e.preventDefault(); // Prevent the default action of the link // Toggle the enlargement state if (enlargement == "on") { enlargement = "off"; // Set to 'off' $(".enlargementBtn").addClass("off"); // Add 'off' class to the button } else { enlargement = "on"; // Set to 'on' $(".enlargementBtn").removeClass("off"); // Remove 'off' class from the button } // Save the new enlargement state to localStorage localStorage.setItem('enlargement', enlargement); location.reload(); // Reload the page to apply changes }); // Observe changes in the document body VM.observe(document.body, () => { // Check if enlargement is enabled if (enlargement == "on") { // Select all room cards in the endless page template const rooms = $(".RoomCard"); // If there are room cards present if (rooms.length > 0) { // Apply a transition effect to room cards for smooth scaling rooms.each(function(i,e){ $(e).css("transition", "transform .1s ease-in-out"); }); // Disable text selection on iPad for better user experience $(".isIpad .list.endless_page_template *") .css("user-select", "none") .css("-webkit-touch-callout", "none"); // Iterate over each room card $(rooms).each((index, element) => { // Get the room name from the data attribute or username const name = $(element).find("> a").data("room") ? $(element).find("> a").data("room") : $(element).find("> .user-info > .username > a").text().replace(/^\s/g, ""); const thumbnail = $(element).find("> a img"); // Get the thumbnail image // Bind pointer events to the room card element $(element) .bind("pointerdown", (event) => { // Release pointer capture on pointer down element.releasePointerCapture(event.pointerId); }) .bind("pointerenter", (event) => { // Handle pointer enter event to scale the room card var firstQ = $("body .RoomCardGrid").innerWidth() / 5, // Calculate first quadrant lastQ = firstQ * 4, // Calculate last quadrant origin = "center center", // Default transform origin originX = "center", // Default horizontal origin originY = "center"; // Default vertical origin // Determine the horizontal origin based on pointer position if (event.pageX < firstQ) { originX = "left"; // Set to left if in the first quadrant } else if (event.pageX > lastQ) { originX = "right"; // Set to right if in the last quadrant } if (event.pageY < $(document).innerHeight() / 4) { originY = "top"; // Set to top if in the upper quarter } else if (event.pageY > $(document).innerHeight() / 4) { originY = "bottom"; // Set to bottom if in the lower quarter } origin = originX + " " + originY; // Combine horizontal and vertical origins if ($(element).parent(".RoomCardGrid").length > 0) { // Scale only on room list $(element) .css("transform-origin", origin) // Set the transform origin .css("transform", "translateX(0px) scale(1.5)") // Scale the room card .css("z-index", "999"); // Bring the room card to the front } }) .bind("pointerup pointerleave", (event) => { // Reset the scaling when pointer is released or leaves the element if ($(element).parent(".RoomCardGrid").length > 0) { // Scale only on room list $(element) .css("transform-origin", "center center") // Reset transform origin .css("transform", "translateX(0px) scale(1)") // Reset scale to normal .css("z-index", "0"); // Reset z-index } }); }); return false; // Prevent default behavior } } }); })();