Wraps CivitAI versions into multiple rows, adds a search bar, and allows for sorting alphabetically.
当前为
// ==UserScript==
// @name Civitai Model Versions Wraparound + Search + Sort
// @version 0.2.0
// @description Wraps CivitAI versions into multiple rows, adds a search bar, and allows for sorting alphabetically.
// @author RedTvpe
// @match https://civitai.com/models/*
// @grant none
// @namespace https://gf.qytechs.cn/users/1418032
// ==/UserScript==
(function () {
'use strict';
// Inject our controls (search, sort, and counter) above the versions container
function injectControls(container) {
// Prevent duplicate insertion
if (document.getElementById('versionControls')) return;
// Create a control panel
const controlPanel = document.createElement('div');
controlPanel.id = 'versionControls';
controlPanel.style.marginBottom = '10px';
// Version counter
const versionCountLabel = document.createElement('span');
versionCountLabel.style.marginRight = '15px';
versionCountLabel.style.fontWeight = 'bold';
versionCountLabel.textContent = `Total Versions: ${container.children.length}`;
// Search input
const searchInput = document.createElement('input');
searchInput.type = 'text';
searchInput.placeholder = 'Search versions...';
searchInput.style.marginRight = '10px';
// Sort buttons
const sortAscBtn = document.createElement('button');
sortAscBtn.textContent = 'Sort A–Z';
sortAscBtn.style.marginRight = '5px';
const sortDescBtn = document.createElement('button');
sortDescBtn.textContent = 'Sort Z–A';
// Append everything to the control panel
controlPanel.appendChild(versionCountLabel);
controlPanel.appendChild(searchInput);
controlPanel.appendChild(sortAscBtn);
controlPanel.appendChild(sortDescBtn);
// Insert the control panel before the versions container
container.parentNode.insertBefore(controlPanel, container);
// Implement search filter
searchInput.addEventListener('input', function () {
const query = searchInput.value.toLowerCase();
const items = container.children;
Array.from(items).forEach(item => {
const text = item.textContent.toLowerCase();
// Show/hide based on whether text includes the query
item.style.display = text.includes(query) ? '' : 'none';
});
});
// Implement sort
sortAscBtn.addEventListener('click', function () {
sortVersions('asc');
});
sortDescBtn.addEventListener('click', function () {
sortVersions('desc');
});
}
// Sort the version items within the container
function sortVersions(order) {
const container = document.querySelector('.mantine-ScrollArea-viewport .mantine-Group-root');
if (!container) return;
// Convert HTMLCollection to an array
const items = Array.from(container.children);
items.sort((a, b) => {
const aText = a.textContent.trim().toLowerCase();
const bText = b.textContent.trim().toLowerCase();
if (aText < bText) return order === 'asc' ? -1 : 1;
if (aText > bText) return order === 'asc' ? 1 : -1;
return 0;
});
// Re-append in sorted order
items.forEach(item => container.appendChild(item));
}
// Apply the layout fix and insert controls
function adjustLayout() {
// Select the container that holds the model versions
const scrollArea = document.querySelector('.mantine-ScrollArea-viewport .mantine-Group-root');
if (scrollArea) {
// Make versions wrap into rows
scrollArea.style.display = 'flex';
scrollArea.style.flexWrap = 'wrap';
scrollArea.style.gap = '8px';
scrollArea.style.overflowX = 'visible';
// Insert our search/sort/counter panel
injectControls(scrollArea);
}
}
// Watch for dynamic content changes
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.addedNodes.length > 0) {
adjustLayout();
}
}
});
// Observe the body for changes
const targetNode = document.querySelector('body');
if (targetNode) {
observer.observe(targetNode, { childList: true, subtree: true });
}
// Run once on load
adjustLayout();
})();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址