Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name Amazon Filter: Must Contain & Exclude + OOS + Clean URL
- // @namespace http://tampermonkey.net/
- // @version 1.7
- // @description Single UI for "must contain" and "exclude" words, hide out-of-stock, and copy clean Amazon URL. Auto-refilters on page updates.
- // @match https://www.amazon.ca/*
- // @grant GM_setClipboard
- // ==/UserScript==
- (function() {
- 'use strict';
- // Arrays to hold filter words:
- // - mustContainWords: user wants these words in the product title
- // - excludeWords: user wants to exclude these words from the product title
- let mustContainWords = [];
- let excludeWords = [];
- // Reference to the "hide out-of-stock" checkbox
- let hideOOSCheckbox = null;
- // --------------------------- COPY CLEAN URL ------------------------------
- function copyCleanAmazonURL() {
- const currentURL = window.location.href;
- // Regex to extract a base URL like: https://www.amazon.ca/.../dp/ABC123XYZ
- const match = currentURL.match(/(https:\/\/www\.amazon\.ca\/.*?\/dp\/[A-Z0-9]+\/?)/);
- if (match) {
- const cleanURL = match[1];
- if (typeof GM_setClipboard === 'function') {
- GM_setClipboard(cleanURL, 'text');
- } else {
- // Fallback if GM_setClipboard isn't available
- navigator.clipboard.writeText(cleanURL)
- .catch(err => console.error('Clipboard write failed:', err));
- }
- alert(`Copied cleaned URL to clipboard: ${cleanURL}`);
- } else {
- alert('No clean Amazon URL could be extracted on this page.');
- }
- }
- // ----------------------- CREATE SINGLE UI PANEL --------------------------
- function createUI() {
- // Main container, fixed at bottom-right
- const uiContainer = document.createElement('div');
- uiContainer.style.position = 'fixed';
- uiContainer.style.bottom = '10px';
- uiContainer.style.right = '10px';
- uiContainer.style.zIndex = '9999';
- uiContainer.style.backgroundColor = '#fff';
- uiContainer.style.padding = '10px';
- uiContainer.style.border = '1px solid #ccc';
- uiContainer.style.borderRadius = '5px';
- uiContainer.style.boxShadow = '0 0 10px rgba(0,0,0,0.1)';
- uiContainer.style.maxWidth = '300px';
- uiContainer.style.fontFamily = 'sans-serif';
- // Title
- const uiTitle = document.createElement('div');
- uiTitle.innerText = 'Amazon Filter & URL Tool';
- uiTitle.style.fontWeight = 'bold';
- uiTitle.style.marginBottom = '5px';
- uiContainer.appendChild(uiTitle);
- // This div will list all (MC) and excluded words
- const wordsList = document.createElement('div');
- wordsList.style.marginBottom = '10px';
- updateWordsList(wordsList);
- uiContainer.appendChild(wordsList);
- // Row for "Must Contain" input + button
- const mustContainRow = document.createElement('div');
- mustContainRow.style.marginBottom = '10px';
- const mustContainLabel = document.createElement('div');
- mustContainLabel.innerText = 'Must Contain:';
- mustContainLabel.style.fontWeight = 'bold';
- mustContainLabel.style.marginBottom = '3px';
- mustContainRow.appendChild(mustContainLabel);
- const mustContainInput = document.createElement('input');
- mustContainInput.type = 'text';
- mustContainInput.placeholder = 'Enter words required';
- mustContainInput.style.padding = '5px';
- mustContainInput.style.width = '100%';
- mustContainRow.appendChild(mustContainInput);
- const mustContainButton = document.createElement('button');
- mustContainButton.innerText = 'Add Must-Contain';
- mustContainButton.style.marginTop = '5px';
- mustContainButton.style.width = '100%';
- mustContainButton.style.padding = '5px 10px';
- mustContainButton.style.cursor = 'pointer';
- mustContainRow.appendChild(mustContainButton);
- mustContainButton.addEventListener('click', () => {
- const newWord = mustContainInput.value.trim().toLowerCase();
- if (newWord && !mustContainWords.includes(newWord)) {
- mustContainWords.push(newWord);
- mustContainInput.value = '';
- updateWordsList(wordsList);
- }
- filterProducts();
- });
- uiContainer.appendChild(mustContainRow);
- // Row for "Exclude" input + button
- const excludeRow = document.createElement('div');
- excludeRow.style.marginBottom = '10px';
- const excludeLabel = document.createElement('div');
- excludeLabel.innerText = 'Exclude (Forbidden Words):';
- excludeLabel.style.fontWeight = 'bold';
- excludeLabel.style.marginBottom = '3px';
- excludeRow.appendChild(excludeLabel);
- const excludeInput = document.createElement('input');
- excludeInput.type = 'text';
- excludeInput.placeholder = 'Enter words to exclude';
- excludeInput.style.padding = '5px';
- excludeInput.style.width = '100%';
- excludeRow.appendChild(excludeInput);
- const excludeButton = document.createElement('button');
- excludeButton.innerText = 'Add Exclude';
- excludeButton.style.marginTop = '5px';
- excludeButton.style.width = '100%';
- excludeButton.style.padding = '5px 10px';
- excludeButton.style.cursor = 'pointer';
- excludeRow.appendChild(excludeButton);
- excludeButton.addEventListener('click', () => {
- const newWord = excludeInput.value.trim().toLowerCase();
- if (newWord && !excludeWords.includes(newWord)) {
- excludeWords.push(newWord);
- excludeInput.value = '';
- updateWordsList(wordsList);
- }
- filterProducts();
- });
- uiContainer.appendChild(excludeRow);
- // Row with the "Hide OOS" checkbox
- const hideOOSRow = document.createElement('div');
- hideOOSRow.style.display = 'flex';
- hideOOSRow.style.alignItems = 'center';
- hideOOSRow.style.marginBottom = '10px';
- hideOOSCheckbox = document.createElement('input');
- hideOOSCheckbox.type = 'checkbox';
- hideOOSCheckbox.style.marginRight = '5px';
- hideOOSRow.appendChild(hideOOSCheckbox);
- const hideOOSLabel = document.createElement('label');
- hideOOSLabel.innerText = 'Hide out-of-stock items';
- hideOOSRow.appendChild(hideOOSLabel);
- // When toggled, re-filter
- hideOOSCheckbox.addEventListener('change', () => {
- filterProducts();
- });
- uiContainer.appendChild(hideOOSRow);
- // "Copy Clean URL" button
- const copyURLButton = document.createElement('button');
- copyURLButton.innerText = 'Copy Clean URL';
- copyURLButton.style.width = '100%';
- copyURLButton.style.padding = '5px 10px';
- copyURLButton.style.cursor = 'pointer';
- copyURLButton.addEventListener('click', () => {
- copyCleanAmazonURL();
- });
- uiContainer.appendChild(copyURLButton);
- // Finally, add this panel to the page
- document.body.appendChild(uiContainer);
- }
- // ----------------------- UPDATE WORDS LIST DISPLAY -----------------------
- function updateWordsList(container) {
- container.innerHTML = '';
- // If we have mustContainWords, list them first
- if (mustContainWords.length > 0) {
- const mcTitle = document.createElement('div');
- mcTitle.innerText = 'Must Contain:';
- mcTitle.style.marginBottom = '3px';
- mcTitle.style.fontWeight = 'bold';
- container.appendChild(mcTitle);
- mustContainWords.forEach(word => {
- const row = document.createElement('div');
- row.style.display = 'flex';
- row.style.alignItems = 'center';
- row.style.marginBottom = '3px';
- const wordLabel = document.createElement('span');
- wordLabel.innerText = `(MC) ${word}`;
- wordLabel.style.marginRight = '10px';
- row.appendChild(wordLabel);
- const removeBtn = document.createElement('span');
- removeBtn.innerText = '❌';
- removeBtn.style.cursor = 'pointer';
- removeBtn.style.color = 'red';
- removeBtn.addEventListener('click', () => {
- mustContainWords = mustContainWords.filter(w => w !== word);
- updateWordsList(container);
- filterProducts();
- });
- row.appendChild(removeBtn);
- container.appendChild(row);
- });
- // Add a small spacing
- const sep = document.createElement('div');
- sep.style.margin = '5px 0';
- container.appendChild(sep);
- }
- // Now excludeWords
- if (excludeWords.length > 0) {
- const exTitle = document.createElement('div');
- exTitle.innerText = 'Excluded Words:';
- exTitle.style.marginBottom = '3px';
- exTitle.style.fontWeight = 'bold';
- container.appendChild(exTitle);
- excludeWords.forEach(word => {
- const row = document.createElement('div');
- row.style.display = 'flex';
- row.style.alignItems = 'center';
- row.style.marginBottom = '3px';
- const wordLabel = document.createElement('span');
- wordLabel.innerText = word;
- wordLabel.style.marginRight = '10px';
- row.appendChild(wordLabel);
- const removeBtn = document.createElement('span');
- removeBtn.innerText = '❌';
- removeBtn.style.cursor = 'pointer';
- removeBtn.style.color = 'red';
- removeBtn.addEventListener('click', () => {
- excludeWords = excludeWords.filter(w => w !== word);
- updateWordsList(container);
- filterProducts();
- });
- row.appendChild(removeBtn);
- container.appendChild(row);
- });
- }
- }
- // ----------------------- FILTER PRODUCTS LOGIC ---------------------------
- function filterProducts() {
- const products = document.querySelectorAll('.s-main-slot .s-result-item');
- const hideOOS = hideOOSCheckbox && hideOOSCheckbox.checked;
- products.forEach(product => {
- let shouldHide = false;
- // 1) Must Contain: if user added mustContainWords, we require
- // the product title to contain *all* of them, or we hide it
- const titleEl = product.querySelector('h2');
- if (titleEl) {
- const titleText = titleEl.innerText.toLowerCase();
- // Must contain check
- if (mustContainWords.length > 0) {
- // The product must contain ALL mustContainWords
- for (const w of mustContainWords) {
- if (!titleText.includes(w)) {
- shouldHide = true;
- break;
- }
- }
- }
- // Exclude check (only do it if not hidden yet)
- if (!shouldHide && excludeWords.length > 0) {
- for (const w of excludeWords) {
- if (titleText.includes(w)) {
- shouldHide = true;
- break;
- }
- }
- }
- }
- // 2) If not hidden yet, check Hide Out-of-Stock
- if (!shouldHide && hideOOS) {
- const productText = product.textContent.toLowerCase();
- if (productText.includes('no featured offers available')) {
- shouldHide = true;
- }
- }
- // Finally show/hide
- product.style.display = shouldHide ? 'none' : '';
- });
- }
- // -------------------- MUTATION OBSERVER FOR AUTO-REFILTER ----------------
- function observeSearchResults() {
- const mainSlot = document.querySelector('.s-main-slot');
- if (!mainSlot) return;
- const observer = new MutationObserver(() => {
- // Whenever the DOM changes in .s-main-slot, re-filter
- filterProducts();
- });
- observer.observe(mainSlot, {
- childList: true,
- subtree: true
- });
- }
- // ------------------------------ INIT -------------------------------------
- window.addEventListener('load', () => {
- createUI();
- observeSearchResults();
- filterProducts(); // Initial run
- });
- })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement