// // // // // global variables var timer; var artTypes = ['🎨','🧑','🏞️']; var imgTypeShown = 0; var log = ''; var editMode = false; var windowWidth = 0; // // // // functions function startUp() { updateFooter(); insertArtists(); insertCheckboxesFromArtistsData(); insertCheckboxesFromCategories(); loadCheckboxesState(); showHideCategories(); loadOptionsState(); loadFavoritesState(); hideAllArtists(); unhideBasedOnPermissiveSetting(); updateArtistsCountPerTag('start'); rotatePromptsImages(); sortArtists(); sortTags(); loadMostUsedTags(); updateArtistsCountPerCategory(); showHideLowCountTags(); } function updateFooter() { let proto = window.location.protocol; if (proto.startsWith('http')) { var footer = document.getElementsByTagName('footer')[0]; footer.classList.add('special'); var el1 = document.createElement('span'); el1.textContent = ''; // footer.querySelectorAll('div')[0].prepend(el1); } } function insertArtists() { // artistsData is defined in the artists_and_tags.js file let missingFiles = ''; var container = document.getElementById('image-container'); let imagePromises = artistsData.map((artist) => { var last = artist[0]; var first = artist[1]; var tags1 = artist[2].replaceAll('|', ' ').toLowerCase(); // class names can't start with a number, but some tags do // in these cases prepending with 'qqqq-' tags1 = tags1.replace(/(^|\s)(\d)/g, '$1qqqq-$2'); var tags2 = artist[2].replaceAll('|', ', ').toLowerCase(); var itemDiv = document.createElement('div'); itemDiv.className = 'image-item ' + tags1; var itemHeader = document.createElement('span'); var h3 = document.createElement('h3'); itemHeader.appendChild(h3); var firstN = document.createElement('span'); var lastN = document.createElement('span'); firstN.className = 'firstN'; lastN.className = 'lastN'; firstN.textContent = `${first}`; lastN.textContent = `${last}`; h3.appendChild(firstN); h3.appendChild(lastN); h3.title = 'copy to clipboard'; var h4 = document.createElement('h4'); h4.textContent = tags2; h4.title = 'check/uncheck these tags'; itemHeader.appendChild(h4); itemDiv.appendChild(itemHeader); var box = document.createElement('div'); var imgTools = document.createElement('div'); imgTools.className = 'imgTools'; var artPrev = document.createElement('div'); artPrev.className = 'art_prev'; var artPrevSpan = document.createElement('span'); artPrevSpan.textContent = '🧑'; artPrev.appendChild(artPrevSpan); imgTools.appendChild(artPrev); var artStar = document.createElement('div'); artStar.className = 'art_star'; var artStarSpan = document.createElement('span'); artStarSpan.textContent = '⭐️'; artStar.appendChild(artStarSpan); imgTools.appendChild(artStar); var artNext = document.createElement('div'); artNext.className = 'art_next'; var artNextSpan = document.createElement('span'); artNextSpan.textContent = '🏞️'; artNext.appendChild(artNextSpan); imgTools.appendChild(artNext); box.appendChild(imgTools); var imgBox = document.createElement('div'); imgBox.className = 'imgBox'; var imgArtwork = document.createElement('img'); var imgPortrait = document.createElement('img'); var imgLandscape = document.createElement('img'); imgArtwork.alt = `${first} ${last}` + ' - artwork'; imgPortrait.alt = `${first} ${last}` + ' - portrait'; imgLandscape.alt = `${first} ${last}` + ' - landscape'; imgArtwork.className = 'img_artwork'; imgPortrait.className = 'img_portrait hidden'; imgLandscape.className = 'img_landscape hidden'; let src = 'images/SDXL_1_0_thumbs/'; if(first == '') { src += last.replaceAll(' ', '_'); } else { src += first.replaceAll(' ', '_') + '_' + last.replaceAll(' ', '_'); } // files use accented characters and huggingface stores the files with this encoding src = encodeURI(src.normalize("NFD")); imgBox.appendChild(imgArtwork); imgBox.appendChild(imgPortrait); imgBox.appendChild(imgLandscape); box.appendChild(imgBox); itemDiv.appendChild(box); container.appendChild(itemDiv); return Promise.allSettled([ new Promise((resolve, reject) => { imgArtwork.onload = resolve; imgArtwork.onerror = () => { missingFiles += '
  • ' + first + '_' + last + '-artwork.webp
  • '; reject(); }; imgArtwork.src = src + '-artwork.webp'; }), new Promise((resolve, reject) => { imgPortrait.onload = resolve; imgPortrait.onerror = () => { missingFiles += '
  • ' + first + '_' + last + '-portrait.webp
  • '; reject(); }; imgPortrait.src = src + '-portrait.webp'; }), new Promise((resolve, reject) => { imgLandscape.onload = resolve; imgLandscape.onerror = () => { missingFiles += '
  • ' + first + '_' + last + '-landscape.webp
  • '; reject(); }; imgLandscape.src = src + '-landscape.webp'; }) ]); }); let report = document.getElementById('missing_images_report'); Promise.allSettled(imagePromises).then(() => { if(missingFiles.indexOf('webp')>0) { report.innerHTML = missingFiles; } else { report.innerHTML = '
  • No thumbnails files are missing! Enlarged images are loaded on hover. If any are missing, they\'ll be listed here at that time.
  • ' } }); } function insertCheckboxesFromArtistsData() { var uniqueTags = new Set(); artistsData.forEach(function(artist) { var tags = artist[2].split('|'); tags.forEach(function(tag) { uniqueTags.add(tag.toLowerCase()); }); }); var uTags = Array.from(uniqueTags); var toggles = document.getElementById('toggles'); for(i=0,il=uTags.length;i 0) { // 👆 shouldn't need to sanitize database, but just in case var label = document.createElement('label'); var el = document.createElement('i'); el.className = 'most_used_indicator'; el.textContent = '+'; var input = document.createElement('input'); input.type = 'checkbox'; input.name = uTags[i]; input.value = uTags[i]; input.checked = true; var span1 = document.createElement('span'); span1.textContent = uTags[i]; var span2 = document.createElement('span'); span2.className = 'count'; label.appendChild(el); label.appendChild(input); label.appendChild(span1); label.appendChild(span2); toggles.appendChild(label); } } var checkAll = document.querySelector('input[name="check-all"]'); var divs = document.querySelectorAll('.image-item'); checkAll.parentNode.querySelector('.count').textContent = ' - ' + divs.length.toLocaleString(); } function insertCheckboxesFromCategories() { var useCategories = document.querySelector('input[name="use_categories"]').checked; for(i=0,il=tagCategories.length;i 2) { imgTypeShown = 0; } } var links = document.getElementById('options_prompts').querySelectorAll('.link'); links.forEach(function(link) { link.classList.remove('selected'); }); if(imgTypeShown == 0) { document.getElementById('promptA').classList.add('selected'); doAlert('Showing artwork'); } else if(imgTypeShown == 1) { document.getElementById('promptP').classList.add('selected'); doAlert('Showing portraits'); } else if(imgTypeShown == 2) { document.getElementById('promptL').classList.add('selected'); doAlert('Showing landscapes'); } } else { if(selected == 'promptA') { imgTypeShown = 0; doAlert('Showing artwork'); } else if(selected == 'promptP') { imgTypeShown = 1; doAlert('Showing portraits'); } else if(selected == 'promptL') { imgTypeShown = 2; doAlert('Showing landscapes'); } var links = document.getElementById(selected).parentNode.querySelectorAll('.link'); links.forEach(function(link) { link.classList.remove('selected'); }); document.getElementById(selected).classList.add('selected'); } } function storeOptionsState() { let state = JSON.parse(localStorage.getItem('tagsChecked')) || {}; if(document.getElementById('promptA').classList.contains('selected')) { state['prompt'] = 'promptA'; } else if(document.getElementById('promptP').classList.contains('selected')) { state['prompt'] = 'promptP'; } else { state['prompt'] = 'promptL'; } if(document.getElementById('sortAR').classList.contains('selected')) { state['artistSort'] = 'sortAR'; } else { state['artistSort'] = 'sortAA'; } if(document.getElementById('sortTC').classList.contains('selected')) { state['tagSort'] = 'sortTC'; } else { state['tagSort'] = 'sortTA'; } localStorage.setItem('tagsChecked', JSON.stringify(state)); } function rotatePromptsImages() { // hide all images let images = document.querySelectorAll('.imgBox img'); images.forEach(function(image) { image.classList.add('hidden'); }); // unhide images matching highlighted option (imgTypeShown) if(imgTypeShown == 0) { images = document.querySelectorAll('.img_artwork'); } else if(imgTypeShown == 1) { images = document.querySelectorAll('.img_portrait'); } else if(imgTypeShown == 2) { images = document.querySelectorAll('.img_landscape'); } images.forEach(function(image) { image.classList.remove('hidden'); }); // switch prev and next button icons let artIndex = 0; artIndex = imgTypeShown-1; if(artIndex < 0) { artIndex = 2; } let prevButtons = document.querySelectorAll('.art_prev span'); prevButtons.forEach(function(span) { span.textContent = artTypes[artIndex]; }); artIndex = imgTypeShown+1; if(artIndex > 2) { artIndex = 0; } let nextButtons = document.querySelectorAll('.art_next span'); nextButtons.forEach(function(span) { span.textContent = artTypes[artIndex]; }); } function updateArtistsCountPerTag(whoCalled) { var permissiveCheckbox = document.querySelector('input[name="mode"]'); var checkboxes = document.querySelectorAll('input[type="checkbox"]'); var divs = document.querySelectorAll('.image-item'); var hiddenDivs = document.querySelectorAll('.image-item.hidden'); if(permissiveCheckbox.checked || whoCalled == 'start') { // on page load, we need to add all the counts first checkboxes.forEach(function(checkbox) { let isTop = checkbox.parentNode.classList.contains('top_control'); if(!isTop) { var theClass = checkbox.name.replace(/(^|\s)(\d)/g, '$1qqqq-$2'); var matchingDivs = document.querySelectorAll('.image-item.' + theClass); var count = matchingDivs.length; checkbox.parentNode.classList.remove('no_matches'); checkbox.parentNode.querySelector('input').disabled = false; checkbox.parentNode.querySelector('.count').textContent = ' - ' + count.toLocaleString(); } }); updateArtistsCountPerCategory(); } if(!permissiveCheckbox.checked) { checkboxes.forEach(function(checkbox) { let isTop = checkbox.parentNode.classList.contains('top_control'); if(!isTop) { var count = 0; // class names can't start with a number, but some tags do // in these cases prepending with 'qqqq-' var theClass = checkbox.name.replace(/(^|\s)(\d)/g, '$1qqqq-$2'); if(!permissiveCheckbox.checked) { // for strict mode, for each checkbox, only count artists with a classes matching all checked checkboxes var matchingDivs = document.querySelectorAll('.image-item.' + theClass + ':not(.hidden)'); count = matchingDivs.length; if(count == 0) { checkbox.parentNode.classList.add('no_matches'); checkbox.parentNode.querySelector('input').disabled = true; } else { checkbox.parentNode.classList.remove('no_matches'); checkbox.parentNode.querySelector('input').disabled = false; } } checkbox.parentNode.querySelector('.count').textContent = ' - ' + count.toLocaleString(); } }); } updateCountOfArtistsShown(divs, hiddenDivs); } function updateArtistsCountPerCategory() { var imageItems = document.querySelectorAll('.image-item'); let counts = []; for(i=0,il=tagCategories.length; i { // class names can't start with a number, // so some classes were prepending with 'qqqq-' // which must be ignored return className.replace(/^qqqq-/, ''); }); for(i=0,il=tagCategories.length; i c.toLowerCase()).some(c => classes.includes(c))) { counts[i]++; } } }); for(i=0,il=tagCategories.length; i