Adds a filter based on thread type
// ==UserScript==
// @name Crazy Factory Thread Filter
// @description Adds a filter based on thread type
// @namespace http://tampermonkey.net/
// @version 1.0
// @match https://www.crazy-factory.com/*
// @grant none
// @author Threadgiver
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// Create filter UI
const panel = document.createElement('div');
panel.style.cssText = `
position: fixed; top: 80px; right: 10px; z-index: 9999;
background: white; border: 1px solid #ccc; border-radius: 6px;
padding: 10px; box-shadow: 0 2px 8px rgba(0,0,0,0.2);
font-family: Arial, sans-serif; font-size: 13px;
`;
panel.innerHTML = `
<div style="font-weight:bold; margin-bottom:8px;">Thread Filter</div>
<label><input type="radio" name="cf_thread" value="all" checked> All</label><br>
<label><input type="radio" name="cf_thread" value="internal"> Internally threaded</label><br>
<label><input type="radio" name="cf_thread" value="external"> Externally threaded</label><br>
<label><input type="radio" name="cf_thread" value="other"> Other / unspecified</label>
`;
document.body.appendChild(panel);
function classifyProduct(el) {
const title = el.querySelector('.title')?.textContent?.toLowerCase() || '';
if (title.includes('internally threaded') || title.includes('internal thread')) return 'internal';
if (title.includes('externally threaded') || title.includes('external thread') ||
(title.includes('threaded') && !title.includes('internally'))) return 'external';
return 'other';
}
function applyFilter(value) {
document.querySelectorAll('li.product').forEach(el => {
if (value === 'all') {
el.style.display = '';
} else {
el.style.display = classifyProduct(el) === value ? '' : 'none';
}
});
}
panel.querySelectorAll('input[name="cf_thread"]').forEach(radio => {
radio.addEventListener('change', e => applyFilter(e.target.value));
});
// Re-apply filter when products load dynamically
const observer = new MutationObserver(() => {
const active = panel.querySelector('input[name="cf_thread"]:checked');
if (active && active.value !== 'all') applyFilter(active.value);
});
const productList = document.getElementById('products');
if (productList) observer.observe(productList, { childList: true, subtree: true });
})();