browser / index.html
qpqpqpqpqpqp's picture
I recommend to rename them, I couldn't get it at a glance
ec8b244 verified
raw
history blame
28.5 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Mal's Models</title>
<script type="text/javascript" src="data-civitai.js"></script>
<script type="text/javascript" src="data-huggingface.js"></script>
<script type="text/javascript" src="comparator.js"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
color: #f1f5f9;
min-height: 100vh;
padding: 20px;
}
a {
text-decoration: none;
color: #60a5fa;
transition: color 0.2s;
}
a:hover {
color: #93c5fd;
}
.header {
max-width: 1400px;
margin: 0 auto 30px;
background: rgba(30, 41, 59, 0.7);
backdrop-filter: blur(10px);
border-radius: 16px;
padding: 24px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
border: 1px solid rgba(148, 163, 184, 0.1);
}
.header h1 {
font-size: 28px;
font-weight: 700;
margin-bottom: 12px;
background: linear-gradient(135deg, #60a5fa 0%, #a78bfa 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-align: center;
}
.profile-links {
display: flex;
flex-wrap: wrap;
gap: 16px;
justify-content: center;
align-items: center;
margin-bottom: 12px;
padding: 12px;
background: rgba(15, 23, 42, 0.4);
border-radius: 8px;
}
.profile-links a {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 12px;
background: rgba(96, 165, 250, 0.1);
border-radius: 6px;
font-size: 14px;
transition: all 0.2s;
}
.profile-links a:hover {
background: rgba(96, 165, 250, 0.2);
transform: translateY(-1px);
}
.last-update {
text-align: center;
font-size: 13px;
color: #94a3b8;
margin-bottom: 16px;
}
.controls {
display: flex;
flex-wrap: wrap;
gap: 12px;
align-items: center;
justify-content: center;
}
.search-container {
flex: 1 1 auto;
min-width: 300px;
max-width: 600px;
position: relative;
}
.search-container input[type="text"] {
width: 100%;
padding: 12px 16px;
padding-right: 100px;
background: rgba(15, 23, 42, 0.6);
border: 2px solid rgba(148, 163, 184, 0.2);
border-radius: 12px;
color: #f1f5f9;
font-size: 15px;
font-family: inherit;
transition: all 0.3s;
}
.search-container input[type="text"]:focus {
outline: none;
border-color: #60a5fa;
background: rgba(15, 23, 42, 0.8);
box-shadow: 0 0 0 4px rgba(96, 165, 250, 0.1);
}
.search-container input[type="text"]::placeholder {
color: #64748b;
}
.clear-btn {
position: absolute;
right: 8px;
top: 50%;
transform: translateY(-50%);
padding: 6px 14px;
background: rgba(239, 68, 68, 0.2);
border: 1px solid rgba(239, 68, 68, 0.3);
border-radius: 8px;
color: #fca5a5;
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
}
.clear-btn:hover {
background: rgba(239, 68, 68, 0.3);
color: #fecaca;
}
.mode-select {
padding: 12px 40px 12px 16px;
background: rgba(15, 23, 42, 0.6);
border: 2px solid rgba(148, 163, 184, 0.2);
border-radius: 12px;
color: #f1f5f9;
font-size: 15px;
font-family: inherit;
cursor: pointer;
transition: all 0.3s;
font-weight: 500;
height: 48px;
line-height: 20px;
min-width: 150px;
flex-shrink: 0;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
background-repeat: no-repeat;
background-position: right 12px center;
background-size: 20px;
box-shadow: none;
outline: none;
}
.mode-select::-ms-expand {
display: none;
}
.mode-select:focus {
outline: none;
border-color: #60a5fa;
box-shadow: 0 0 0 4px rgba(96, 165, 250, 0.1);
}
.mode-select option {
background: #0f172a;
color: #e2e8f0;
padding: 16px 20px;
font-size: 15px;
font-weight: 500;
border: none;
outline: none;
}
.mode-select option:hover {
background: linear-gradient(90deg, rgba(96, 165, 250, 0.15) 0%, rgba(96, 165, 250, 0.05) 100%);
color: #60a5fa;
font-weight: 600;
}
.mode-select option:checked,
.mode-select option:focus {
background: linear-gradient(90deg, rgba(96, 165, 250, 0.25) 0%, rgba(96, 165, 250, 0.15) 100%);
color: #93c5fd;
font-weight: 600;
box-shadow: none;
outline: none;
}
.checkbox-group {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
}
.checkbox-label {
display: flex;
align-items: center;
gap: 8px;
padding: 10px 16px;
background: rgba(15, 23, 42, 0.4);
border: 2px solid rgba(148, 163, 184, 0.2);
border-radius: 10px;
cursor: pointer;
transition: all 0.2s;
font-size: 14px;
font-weight: 500;
user-select: none;
}
.checkbox-label:hover {
background: rgba(15, 23, 42, 0.6);
border-color: rgba(148, 163, 184, 0.3);
}
.checkbox-label input[type="checkbox"] {
width: 18px;
height: 18px;
cursor: pointer;
accent-color: #60a5fa;
}
.checkbox-label input[type="checkbox"]:checked + span {
color: #60a5fa;
}
.stats-bar {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 20px;
background: rgba(15, 23, 42, 0.6);
border-radius: 10px;
font-size: 14px;
font-weight: 600;
flex-shrink: 0;
}
.stats-bar label {
color: #94a3b8;
}
.stats-bar input {
width: 70px;
padding: 6px 10px;
background: rgba(30, 41, 59, 0.8);
border: 1px solid rgba(148, 163, 184, 0.2);
border-radius: 6px;
color: #60a5fa;
text-align: center;
font-weight: 700;
font-size: 16px;
}
.mainContent {
max-width: 1400px;
margin: 0 auto;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
gap: 20px;
padding: 0 4px;
}
.element {
background: rgba(30, 41, 59, 0.6);
backdrop-filter: blur(10px);
border-radius: 16px;
overflow: hidden;
border: 1px solid rgba(148, 163, 184, 0.1);
transition: all 0.3s;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
display: flex;
flex-direction: column;
cursor: pointer;
}
.element:hover {
transform: translateY(-4px);
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4);
border-color: rgba(96, 165, 250, 0.3);
}
.element .modelName {
padding: 14px 16px;
background: rgba(15, 23, 42, 0.8);
font-weight: 600;
font-size: 14px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
border-bottom: 1px solid rgba(148, 163, 184, 0.1);
color: #e2e8f0;
}
.element .imageContainer {
position: relative;
width: 100%;
padding-top: 137.5%; /* 192/264 aspect ratio */
overflow: hidden;
background: rgba(15, 23, 42, 0.6);
}
.element .imageContainer img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s;
}
.element:hover .imageContainer img {
transform: scale(1.05);
}
.statsBox {
padding: 16px;
background: rgba(15, 23, 42, 0.8);
font-size: 13px;
line-height: 1.8;
flex: 1;
display: none; /* Hidden in main view */
}
.statsBox .stat-row {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 6px;
}
.statsBox .stat-row:last-child {
margin-bottom: 0;
}
.statsBox .stat-label {
font-weight: 600;
color: #94a3b8;
min-width: 75px;
}
.statsBox .stat-value {
display: flex;
align-items: center;
gap: 6px;
}
/* Modal Styles */
.modal-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.8);
backdrop-filter: blur(8px);
z-index: 1000;
align-items: center;
justify-content: center;
padding: 20px;
animation: fadeIn 0.2s ease-out;
}
.modal-overlay.active {
display: flex;
}
.modal-content {
background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);
border-radius: 20px;
max-width: 1100px;
width: 100%;
max-height: 90vh;
overflow: hidden;
position: relative;
border: 2px solid rgba(148, 163, 184, 0.2);
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
animation: slideUp 0.3s ease-out;
display: flex;
flex-direction: column;
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.modal-header {
padding: 24px;
border-bottom: 1px solid rgba(148, 163, 184, 0.1);
display: flex;
align-items: center;
justify-content: space-between;
position: sticky;
top: 0;
background: rgba(30, 41, 59, 0.95);
backdrop-filter: blur(10px);
z-index: 10;
}
.modal-title {
font-size: 24px;
font-weight: 700;
color: #f1f5f9;
margin: 0;
}
.modal-close {
width: 36px;
height: 36px;
border-radius: 10px;
background: rgba(239, 68, 68, 0.2);
border: 1px solid rgba(239, 68, 68, 0.3);
color: #fca5a5;
font-size: 20px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
font-weight: 700;
}
.modal-close:hover {
background: rgba(239, 68, 68, 0.3);
color: #fecaca;
transform: rotate(90deg);
}
.modal-body {
display: flex;
flex: 1;
overflow: hidden;
gap: 0;
}
.modal-left {
flex: 0 0 45%;
display: flex;
align-items: center;
justify-content: center;
background: rgba(15, 23, 42, 0.6);
padding: 24px;
}
.modal-image-container {
width: 100%;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
max-height: 100%;
}
.modal-image-container img {
width: 100%;
height: auto;
display: block;
}
.modal-right {
flex: 1;
padding: 24px;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 16px;
}
.modal-stats {
display: grid;
gap: 12px;
}
.modal-stat-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 20px;
background: rgba(15, 23, 42, 0.6);
border-radius: 12px;
border: 1px solid rgba(148, 163, 184, 0.1);
transition: all 0.2s;
}
.modal-stat-row:hover {
background: rgba(15, 23, 42, 0.8);
border-color: rgba(148, 163, 184, 0.2);
}
.modal-stat-label {
font-weight: 600;
font-size: 15px;
color: #cbd5e1;
}
.modal-stat-value {
display: flex;
align-items: center;
gap: 12px;
}
.modal-hf-link {
padding: 6px 12px;
background: rgba(255, 107, 0, 0.15);
border: 1px solid rgba(255, 107, 0, 0.3);
border-radius: 8px;
font-size: 12px;
font-weight: 600;
color: #ff9d5c;
transition: all 0.2s;
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 6px;
}
.modal-hf-link:hover {
background: rgba(255, 107, 0, 0.25);
border-color: rgba(255, 107, 0, 0.5);
transform: translateY(-1px);
color: #ffb380;
}
.modal-hf-placeholder {
padding: 6px 12px;
background: rgba(100, 116, 139, 0.15);
border: 1px solid rgba(100, 116, 139, 0.3);
border-radius: 8px;
font-size: 12px;
font-weight: 600;
color: #94a3b8;
display: inline-flex;
align-items: center;
gap: 6px;
opacity: 0.5;
}
.hf-logo {
width: 16px;
height: 16px;
display: inline-block;
}
@media (max-width: 900px) {
.modal-body {
flex-direction: column;
}
.modal-left {
flex: 0 0 auto;
max-height: 400px;
}
.modal-right {
flex: 1;
}
}
.status-icon {
font-size: 16px;
display: inline-block;
}
.status-available {
color: #4ade80;
}
.status-unavailable {
color: #f87171;
}
.status-unknown {
color: #fbbf24;
}
.hf-link {
padding: 2px 8px;
background: rgba(96, 165, 250, 0.1);
border: 1px solid rgba(96, 165, 250, 0.2);
border-radius: 6px;
font-size: 11px;
font-weight: 600;
color: #60a5fa;
transition: all 0.2s;
display: inline-block;
}
.hf-link:hover {
background: rgba(96, 165, 250, 0.2);
border-color: rgba(96, 165, 250, 0.4);
}
@media (max-width: 768px) {
.controls {
flex-direction: column;
align-items: stretch;
}
.checkbox-group {
justify-content: center;
}
.mainContent {
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
gap: 16px;
}
}
/* Loading animation */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.element {
animation: fadeIn 0.4s ease-out;
}
/* Scrollbar styling */
::-webkit-scrollbar {
width: 12px;
}
::-webkit-scrollbar-track {
background: rgba(15, 23, 42, 0.5);
}
::-webkit-scrollbar-thumb {
background: rgba(148, 163, 184, 0.3);
border-radius: 6px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(148, 163, 184, 0.5);
}
</style>
</head>
<body>
<div class="header">
<h1>🎨 Mal's Models</h1>
<div class="profile-links">
<a href="https://civitai.com/user/malcolmrey" target="_blank">🎨 CivitAI</a>
<a href="https://huggingface.com/malcolmrey" target="_blank">🤗 HuggingFace</a>
<a href="https://buymeacoffee.com/malcolmrey" target="_blank">☕ BuyMeACoffee</a>
<a href="https://reddit.com/r/malcolmrey" target="_blank">💬 Reddit</a>
</div>
<div class="last-update">Last updated: 2025.11.02</div>
<div class="controls">
<div class="search-container">
<input
id="search"
type="text"
onkeyup="javascript:searchModels(this.value);"
placeholder="Search models..."
/>
<button
class="clear-btn"
onclick="javascript:clearCurrentSearchValue(); javascript:searchModels(getCurrentSearchValue())"
>
Clear
</button>
</div>
<select
class="mode-select"
id="searchMode"
onchange="javascript:searchModels(getCurrentSearchValue());"
>
<option value="available">Include</option>
<option value="missing">Exclude</option>
</select>
<div class="stats-bar">
<label>Found:</label>
<input id="found" type="text" readonly />
</div>
</div>
<div class="controls" style="margin-top: 16px;">
<div class="checkbox-group">
<label class="checkbox-label">
<input
id="selectedLora"
type="checkbox"
onclick="javascript:searchModels(getCurrentSearchValue());"
/>
<span>SD LoRA</span>
</label>
<label class="checkbox-label">
<input
id="selectedLocon"
type="checkbox"
onclick="javascript:searchModels(getCurrentSearchValue());"
/>
<span>SD LoCon</span>
</label>
<label class="checkbox-label">
<input
id="selectedEmbedding"
type="checkbox"
onclick="javascript:searchModels(getCurrentSearchValue());"
/>
<span>SD Embedding</span>
</label>
<label class="checkbox-label">
<input
id="selectedFlux"
type="checkbox"
onclick="javascript:searchModels(getCurrentSearchValue());"
/>
<span>Flux</span>
</label>
<label class="checkbox-label">
<input
id="selectedWan"
type="checkbox"
onclick="javascript:searchModels(getCurrentSearchValue());"
/>
<span>WAN</span>
</label>
<label class="checkbox-label">
<input
id="selectedSdxl"
type="checkbox"
onclick="javascript:searchModels(getCurrentSearchValue());"
/>
<span>SDXL</span>
</label>
<label class="checkbox-label">
<input
id="selectedQwen"
type="checkbox"
onclick="javascript:searchModels(getCurrentSearchValue());"
/>
<span>Qwen</span>
</label>
</div>
</div>
</div>
<div id="mainContent" class="mainContent"></div>
<!-- Modal -->
<div id="modalOverlay" class="modal-overlay" onclick="closeModalOnOverlay(event)">
<div class="modal-content" onclick="event.stopPropagation()">
<div class="modal-header">
<h2 id="modalTitle" class="modal-title"></h2>
<button class="modal-close" onclick="closeModal()" aria-label="Close">×</button>
</div>
<div class="modal-body">
<div class="modal-left">
<div class="modal-image-container">
<img id="modalImage" src="" alt="" />
</div>
</div>
<div class="modal-right">
<div id="modalStats" class="modal-stats"></div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
function yesNo(value) {
if (value === undefined) {
return '<span class="status-icon status-unknown">❓</span>';
}
return value
? '<span class="status-icon status-available">✅</span>'
: '<span class="status-icon status-unavailable">❌</span>';
}
function formatHFLink(link, hasHF) {
if (!link) return '';
return `<a href="${link}" target="_blank" class="hf-link">HF</a>`;
}
function formatModalHFLink(isAvailable, link) {
if (isAvailable && link) {
return `<a href="${link}" target="_blank" class="modal-hf-link">🤗 HuggingFace</a>`;
} else if (isAvailable) {
return `<span class="modal-hf-placeholder">🤗 HuggingFace</span>`;
}
return '';
}
function openModal(element) {
const modal = document.getElementById('modalOverlay');
const modalTitle = document.getElementById('modalTitle');
const modalImage = document.getElementById('modalImage');
const modalStats = document.getElementById('modalStats');
// Generate HuggingFace links
const personName = element.key;
const loconHFLink = element.locon
? `https://huggingface.co/malcolmrey/lycoris/resolve/main/locon_${personName}_v1_from_v1_64_32.safetensors`
: undefined;
const loraHFLink = undefined; // We don't know the hyphenation pattern for loras
const embeddingHFLink = element.embedding
? `https://huggingface.co/malcolmrey/embeddings/resolve/main/${personName}-ti.safetensors`
: undefined;
const fluxHFLink = element.flux
? `https://huggingface.co/malcolmrey/flux/resolve/main/flux_${personName}_v1-step00000400.safetensors`
: undefined;
const wanHFLink = element.wan
? `https://huggingface.co/malcolmrey/wan/resolve/main/wan2.1/wan_${personName}_v1.safetensors`
: undefined;
modalTitle.textContent = element.key;
modalImage.src = element.imageUrl ?? unknownImage;
modalImage.alt = element.key;
modalStats.innerHTML = `
<div class="modal-stat-row">
<span class="modal-stat-label">SD LoCon</span>
<span class="modal-stat-value">
${yesNo(element.locon)}
${formatModalHFLink(element.locon, loconHFLink)}
</span>
</div>
<div class="modal-stat-row">
<span class="modal-stat-label">SD LoRA</span>
<span class="modal-stat-value">
${yesNo(element.lora)}
${formatModalHFLink(element.lora, loraHFLink)}
</span>
</div>
<div class="modal-stat-row">
<span class="modal-stat-label">SD Embedding</span>
<span class="modal-stat-value">
${yesNo(element.embedding)}
${formatModalHFLink(element.embedding, embeddingHFLink)}
</span>
</div>
<div class="modal-stat-row">
<span class="modal-stat-label">Flux</span>
<span class="modal-stat-value">
${yesNo(element.flux)}
${formatModalHFLink(element.flux, fluxHFLink)}
</span>
</div>
<div class="modal-stat-row">
<span class="modal-stat-label">WAN</span>
<span class="modal-stat-value">
${yesNo(element.wan)}
${formatModalHFLink(element.wan, wanHFLink)}
</span>
</div>
<div class="modal-stat-row">
<span class="modal-stat-label">SDXL</span>
<span class="modal-stat-value">
${yesNo(element.sdxl)}
${formatModalHFLink(element.sdxl, element.sdxlHFLink)}
</span>
</div>
<div class="modal-stat-row">
<span class="modal-stat-label">Qwen</span>
<span class="modal-stat-value">
${yesNo(element.qwen)}
${formatModalHFLink(element.qwen, element.qwenHFLink)}
</span>
</div>
`;
modal.classList.add('active');
document.body.style.overflow = 'hidden';
}
function closeModal() {
const modal = document.getElementById('modalOverlay');
modal.classList.remove('active');
document.body.style.overflow = '';
}
function closeModalOnOverlay(event) {
if (event.target.id === 'modalOverlay') {
closeModal();
}
}
// Close modal on ESC key
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape') {
closeModal();
}
});
const notMatched = {
lycoris: [],
lora: [],
embedding: [],
flux: [],
wan: [],
sdxl: [],
qwen: [],
};
models.lycorises.forEach((lycoris) => {
const key = prepareKey(lycoris.name);
if (presence[key] !== undefined) {
presence[key].loconCivitai = true;
setImageUrl(key, lycoris.imageUrl);
presence[key].loconCivitaiLink = lycoris.url;
} else if (!isKnownSkippableKey(key)) {
notMatched.lycoris.push(key);
}
});
models.loras.forEach((lora) => {
const key = prepareKey(lora.name);
if (presence[key] !== undefined) {
presence[key].loraCivitai = true;
setImageUrl(key, lora.imageUrl);
presence[key].loraCivitaiLink = lora.url;
} else if (!isKnownSkippableKey(key)) {
notMatched.lora.push(key);
}
});
models.embeddings.forEach((embedding) => {
const key = prepareKey(embedding.name);
if (presence[key] !== undefined) {
presence[key].embeddingCivitai = true;
setImageUrl(key, embedding.imageUrl);
presence[key].embeddingCivitaiLink = embedding.url;
} else if (!isKnownSkippableKey(key)) {
notMatched.embedding.push(key);
}
});
models.fluxes.forEach((flux) => {
const key = prepareKey(flux.name);
if (presence[key] !== undefined) {
presence[key].fluxCivitai = true;
setImageUrl(key, flux.imageUrl);
presence[key].fluxCivitaiLink = flux.url;
} else if (!isKnownSkippableKey(key)) {
notMatched.flux.push(key);
}
});
models.wans.forEach((wan) => {
const key = prepareKey(wan.name);
if (presence[key] !== undefined) {
presence[key].wanCivitai = true;
setImageUrl(key, wan.imageUrl);
presence[key].wanCivitaiLink = wan.url;
} else if (!isKnownSkippableKey(key)) {
notMatched.wan.push(key);
}
});
models.sdxls.forEach((sdxl) => {
const key = prepareKey(sdxl.name);
if (presence[key] !== undefined) {
presence[key].sdxlCivitai = true;
setImageUrl(key, sdxl.imageUrl);
presence[key].sdxlCivitaiLink = sdxl.url;
} else if (!isKnownSkippableKey(key)) {
notMatched.sdxl.push(key);
}
});
models.qwens.forEach((qwen) => {
const key = prepareKey(qwen.name);
if (presence[key] !== undefined) {
presence[key].qwenCivitai = true;
setImageUrl(key, qwen.imageUrl);
presence[key].qwenCivitaiLink = qwen.url;
} else if (!isKnownSkippableKey(key)) {
notMatched.qwen.push(key);
}
});
console.log(notMatched);
const presenceModels = [];
for (const property in presence) {
const element = {
key: property,
locon: presence[property].locon,
lora: presence[property].lora,
embedding: presence[property].embedding,
flux: presence[property].flux,
wan: presence[property].wan,
sdxl: presence[property].sdxl,
qwen: presence[property].qwen,
mega: undefined,
imageUrl: presence[property]?.imageUrl ?? undefined,
loconHFLink: presence[property]?.loconHFLink,
loraHFLink: presence[property]?.loraHFLink,
embeddingHFLink: presence[property]?.embeddingHFLink,
fluxHFLink: presence[property]?.fluxHFLink,
wanHFLink: presence[property]?.wanHFLink,
sdxlHFLink: presence[property]?.sdxlHFLink,
qwenHFLink: presence[property]?.qwenHFLink,
};
presenceModels.push(element);
}
function searchModelsModern(value) {
const lowerCaseValue = value.toLowerCase();
const filtered = presenceModels.filter((element) => {
return (
(element.key.toLowerCase().includes(lowerCaseValue) || value === '*') &&
filterByType(element)
);
});
document.getElementById('found').value = filtered.length;
const contentDiv = document.getElementById('mainContent');
contentDiv.innerHTML = '';
filtered.forEach((element, index) => {
const card = document.createElement('div');
card.className = 'element';
card.innerHTML = `
<div class="modelName" title="${escapeHtml(element.key)}">${element.key}</div>
<div class="imageContainer">
<img src="${element.imageUrl ?? unknownImage}" alt="${escapeHtml(element.key)}" />
</div>
`;
card.addEventListener('click', () => openModal(element));
contentDiv.appendChild(card);
});
}
// Override the searchModels function
window.searchModels = searchModelsModern;
searchModels(getCurrentSearchValue());
</script>
</body>
</html>