🏠 Home 

Draggable Google Search Tool with Copy Link

Create a stylish, draggable search form with persistent inputs, paste buttons, and a copy dynamic link button for Google search r###lts. The form retains user-given values and is initially positioned on the right side but can be moved anywhere. Includes a copy dynamic link button that copies the first available link from specified classes. Now with smaller text size, larger checkboxes, and aligned buttons.


Install this script?
// ==UserScript==
// @name         Draggable Google Search Tool with Copy Link
// @namespace    http://tampermonkey.net/
// @version      1.27
// @description  Create a stylish, draggable search form with persistent inputs, paste buttons, and a copy dynamic link button for Google search r###lts. The form retains user-given values and is initially positioned on the right side but can be moved anywhere. Includes a copy dynamic link button that copies the first available link from specified classes. Now with smaller text size, larger checkboxes, and aligned buttons.
// @author       Mahmudul Hasan Shawon
// @match        https://www.google.com/search?*
// @license      MIT
// @grant        none
// ==/UserScript==
(function() {
'use strict';
// Load Inter font
const interFontLink = document.createElement('link');
interFontLink.href = 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap';
interFontLink.rel = 'stylesheet';
document.head.appendChild(interFontLink);
// Default values
const defaultInput1Value = 'Company Name';
const defaultInput2Value = 'City,State';
const defaultInput3Value = 'Headquarter';
// Retrieve stored values or use default
const storedInput1Value = localStorage.getItem('input1') || defaultInput1Value;
const storedInput2Value = localStorage.getItem('input2') || defaultInput2Value;
const storedInput3Value = localStorage.getItem('input3') || defaultInput3Value;
// Create a container for the form
const formContainer = document.createElement('div');
formContainer.style.position = 'fixed';
formContainer.style.top = '10px';
formContainer.style.right = '20px'; // Positioning to the right side
formContainer.style.padding = '10px';
formContainer.style.backgroundColor = '#d8d3ff';
//formContainer.style.backdropFilter = 'blur(10px)';
//formContainer.style.backgroundColor = 'rgba(255, 255, 255, 0.2)'; // Optional for semi-transparent background
formContainer.style.border = '2px solid #ffff';
formContainer.style.borderRadius = '16px';
formContainer.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.1)';
formContainer.style.zIndex = '10000';
formContainer.style.fontFamily = "'Inter', sans-serif";
formContainer.style.cursor = 'move';
formContainer.style.maxWidth = '300px'; // Adjusted width for right-side positioning
formContainer.style.boxSizing = 'border-box';
// Create the form element
const form = document.createElement('form');
form.style.display = 'flex';
form.style.flexDirection = 'column';
form.style.gap = '8px'; // Adjusted gap
// Function to create input field with paste button and optional checkbox
const createInputFieldWithExtras = (id, value, includeCheckbox = false) => {
const inputWrapper = document.createElement('div');
inputWrapper.style.position = 'relative';
inputWrapper.style.display = 'flex';
inputWrapper.style.alignItems = 'center';
inputWrapper.style.gap = '8px'; // Adjusted gap
const input = document.createElement('input');
input.type = 'text';
input.value = value;
input.id = id;
input.style.padding = '8px'; // Adjusted padding
input.style.border = '0px solid #ffffff';
input.style.borderRadius = '8px'; // Adjusted border radius
input.style.fontFamily = "'Inter', sans-serif";
input.style.fontSize = '12px'; // Adjusted font size
//input.style.backgroundColor = '#ffffff';
input.style.backdropFilter = 'blur(10px)';
input.style.backgroundColor = 'rgba(255, 255, 255, 0.4)'; // Optional for semi-transparent background
input.style.boxShadow = '0 1px 3px rgba(0, 0, 0, 0.1)'; // Adjusted shadow
input.style.color = '#000000';
// Add event listener to save to localStorage on change
input.addEventListener('input', () => {
localStorage.setItem(id, input.value.trim());
});
inputWrapper.appendChild(input);
const pasteButton = document.createElement('button');
pasteButton.type = 'button';
pasteButton.innerText = '📝';
pasteButton.style.padding = '8px 8px'; // Adjusted padding
pasteButton.style.border = 'none';
//pasteButton.style.backgroundColor = '#7469B6';
pasteButton.style.backdropFilter = 'blur(10px)';
pasteButton.style.backgroundColor = 'rgba(255, 255, 255, 0.4)'; // Optional for semi-transparent background
pasteButton.style.color = '#fff';
pasteButton.style.borderRadius = '8px'; // Adjusted border radius
pasteButton.style.cursor = 'pointer';
pasteButton.style.fontFamily = "'Inter', sans-serif";
pasteButton.style.fontSize = '12px'; // Adjusted font size
pasteButton.addEventListener('click', async () => {
input.value = await navigator.clipboard.readText();
localStorage.setItem(id, input.value.trim()); // Save updated value to localStorage
});
inputWrapper.appendChild(pasteButton);
if (includeCheckbox) {
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.id = `checkbox-${id}`;
checkbox.style.width = '20px'; // Adjusted width
checkbox.style.height = '20px'; // Adjusted height
checkbox.style.marginLeft = '8px'; // Adjusted margin
checkbox.style.cursor = 'pointer';
checkbox.style.border = '0px solid #cccccc'; // Optional: Border for visibility
checkbox.style.borderRadius = '12px';
checkbox.style.appearance = 'none'; // Remove default checkbox styles
checkbox.style.backgroundColor = '#ffffff'; // Default to white
checkbox.style.display = 'inline-block';
// Change background color when selected
checkbox.addEventListener('change', () => {
checkbox.style.backgroundColor = checkbox.checked ? '#0ad400' : '#ffffff'; // Green when checked, white otherwise
});
inputWrapper.appendChild(checkbox);
}
return inputWrapper;
};
// Create the input fields
const input1 = createInputFieldWithExtras('input1', storedInput1Value, false);
const input2 = createInputFieldWithExtras('input2', storedInput2Value, true);
const input3 = createInputFieldWithExtras('input3', storedInput3Value, true);
// Create a container for the buttons
const buttonContainer = document.createElement('div');
buttonContainer.style.display = 'flex';
buttonContainer.style.justifyContent = 'space-between'; // Align buttons to the edges
buttonContainer.style.alignItems = 'center'; // Align items vertically
buttonContainer.style.gap = '8px'; // Adjusted gap
// Create the copy dynamic link button
const copyLinkButton = document.createElement('button');
copyLinkButton.type = 'button';
copyLinkButton.innerText = 'Copy Link';
copyLinkButton.style.padding = '8px'; // Adjusted padding
copyLinkButton.style.width = '48%';
copyLinkButton.style.backgroundColor = '#8700ff';
copyLinkButton.style.color = '#fff';
copyLinkButton.style.border = 'none';
copyLinkButton.style.borderRadius = '60px'; // Adjusted border radius
copyLinkButton.style.cursor = 'pointer';
copyLinkButton.style.fontSize = '12px'; // Adjusted font size
copyLinkButton.style.fontWeight = 'bold';
copyLinkButton.style.fontFamily = "'Inter', sans-serif";
copyLinkButton.addEventListener('click', async () => {
const link = getFirstAvailableLink();
if (link) {
await copyToClipboard(link);
} else {
showCustomAlert('No link available to copy.');
}
});
// Create the search button
const searchButton = document.createElement('button');
searchButton.type = 'button';
searchButton.innerText = 'Search';
searchButton.style.padding = '8px'; // Adjusted padding
searchButton.style.width = '48%';
searchButton.style.backgroundColor = '#000000';
searchButton.style.color = '#fff';
searchButton.style.border = 'none';
searchButton.style.borderRadius = '60px'; // Adjusted border radius
searchButton.style.cursor = 'pointer';
searchButton.style.fontSize = '12px'; // Adjusted font size
searchButton.style.fontWeight = 'bold';
searchButton.style.fontFamily = "'Inter', sans-serif";
searchButton.style.marginLeft = 'auto'; // Push search button to the right
searchButton.addEventListener('click', () => {
let query = input1.querySelector('input').value.trim();
const checkbox2 = document.getElementById(`checkbox-input2`);
const checkbox3 = document.getElementById(`checkbox-input3`);
if (checkbox2.checked) query += ` ${input2.querySelector('input').value.trim()}`;
if (checkbox3.checked) query += ` ${input3.querySelector('input').value.trim()}`;
const searchUrl = `https://www.google.com/search?q=${encodeURIComponent(query)}`;
window.location.href = searchUrl;
// Save values to localStorage
localStorage.setItem('input1', input1.querySelector('input').value.trim());
localStorage.setItem('input2', input2.querySelector('input').value.trim());
localStorage.setItem('input3', input3.querySelector('input').value.trim());
});
// Append buttons to the button container
buttonContainer.appendChild(copyLinkButton);
buttonContainer.appendChild(searchButton);
// Append input fields and button container to the form
form.appendChild(input1);
form.appendChild(input2);
form.appendChild(input3);
form.appendChild(buttonContainer);
// Append form to the container
formContainer.appendChild(form);
// Append form container to the body
document.body.appendChild(formContainer);
// Function to show custom alerts
const showCustomAlert = (message) => {
const alertBox = document.createElement('div');
alertBox.textContent = message;
alertBox.style.position = 'fixed';
alertBox.style.bottom = '680px';
alertBox.style.right = '20px';
alertBox.style.padding = '10px';
alertBox.style.backgroundColor = '#ff0000';
alertBox.style.color = '#fff';
alertBox.style.borderRadius = '5px';
alertBox.style.boxShadow = '0 2px 4px rgba(0, 0, 0, 0.2)';
alertBox.style.zIndex = '10001';
alertBox.style.fontFamily = "'Inter', sans-serif";
alertBox.style.opacity = '1';
alertBox.style.transition = 'opacity 0.5s ease'; // Smooth transition
document.body.appendChild(alertBox);
setTimeout(() => {
alertBox.style.opacity = '0';
setTimeout(() => alertBox.remove(), 500); // Delay removal until fade-out completes
}, 1000);
};
// Draggable functionality
formContainer.addEventListener('mousedown', (e) => {
if (e.target === formContainer) {
let offsetX = e.clientX - formContainer.getBoundingClientRect().left;
let offsetY = e.clientY - formContainer.getBoundingClientRect().top;
const mouseMoveHandler = (e) => {
formContainer.style.left = `${e.clientX - offsetX}px`;
formContainer.style.top = `${e.clientY - offsetY}px`;
};
const mouseUpHandler = () => {
document.removeEventListener('mousemove', mouseMoveHandler);
document.removeEventListener('mouseup', mouseUpHandler);
};
document.addEventListener('mousemove', mouseMoveHandler);
document.addEventListener('mouseup', mouseUpHandler);
}
});
// Function to copy text to clipboard
const copyToClipboard = async (text) => {
try {
await navigator.clipboard.writeText(text);
showCustomAlert('Link copied to clipboard!');
} catch (err) {
console.error('Failed to copy: ', err);
showCustomAlert('Failed to copy link.');
}
};
const getFirstAvailableLink = () => {
// Extended class names to check
const classNamesToCheck = ['n1obkb', 'ab_button', 'ellip', 'PZPZlf'];
// Check for direct <a> tags and those within a <div> or other container
for (const className of classNamesToCheck) {
// Select all <a> elements with the class
const links = document.querySelectorAll(`a.${className}[href]`);
// If direct matches are found, return the first href
if (links.length > 0) {
return links[0].href; // Return the href of the first found link
}
// Check for <a> tags within other elements with the class name
const containers = document.querySelectorAll(`div.${className}, button.${className}`);
for (let container of containers) {
const childLinks = container.querySelectorAll('a[href]');
if (childLinks.length > 0) {
return childLinks[0].href;
}
}
}
// Return null if no link is found
return null;
};
})();