Mattthew commited on
Commit
62230ad
1 Parent(s): 6ecc6ba

ground truth comparison images and other improvements

Browse files

ground truth "model" to compare SD output with the artists' work
easier method of switching between the 4 models
all female artists identified and tagged

Files changed (4) hide show
  1. artists_and_tags.js +0 -0
  2. index.css +41 -6
  3. index.html +32 -24
  4. index.js +170 -162
artists_and_tags.js CHANGED
The diff for this file is too large to render. See raw diff
 
index.css CHANGED
@@ -1000,12 +1000,13 @@ input[type="checkbox"]:checked::before {
1000
  top: 0;
1001
  right: 0;
1002
  border-bottom-left-radius: 4px;
 
1003
  }
1004
 
1005
  .image-item .imgTools > a.art_search {
1006
- bottom: 0;
1007
- left: 0;
1008
- border-top-right-radius: 4px;
1009
  }
1010
 
1011
  .image-item .imgTools > div.art_star {
@@ -1029,9 +1030,8 @@ input[type="checkbox"]:checked::before {
1029
 
1030
  .image-item .imgTools > div.art_set {
1031
  bottom: 0;
1032
- left: 60px;
1033
- width: 136px;
1034
- border-top-left-radius: 4px;
1035
  border-top-right-radius: 4px;
1036
  padding: 13px;
1037
  box-sizing: border-box;
@@ -1053,6 +1053,41 @@ input[type="checkbox"]:checked::before {
1053
  overflow: hidden;
1054
  }
1055
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1056
  .image-item .imgBox {
1057
  position: relative;
1058
  z-index: 0;
 
1000
  top: 0;
1001
  right: 0;
1002
  border-bottom-left-radius: 4px;
1003
+ display: none;
1004
  }
1005
 
1006
  .image-item .imgTools > a.art_search {
1007
+ top: 0;
1008
+ right: 0;
1009
+ border-bottom-left-radius: 4px;
1010
  }
1011
 
1012
  .image-item .imgTools > div.art_star {
 
1030
 
1031
  .image-item .imgTools > div.art_set {
1032
  bottom: 0;
1033
+ left: 0px;
1034
+ width: 196px;
 
1035
  border-top-right-radius: 4px;
1036
  padding: 13px;
1037
  box-sizing: border-box;
 
1053
  overflow: hidden;
1054
  }
1055
 
1056
+ .image-item .art_set span.prev:hover {
1057
+ background: linear-gradient(90deg, #333 40%, #666 100%);
1058
+ }
1059
+
1060
+ .image-item .art_set span.next:hover {
1061
+ background: linear-gradient(90deg, #666 60%, #333 100%);
1062
+ }
1063
+
1064
+ .image-item .art_set span::after {
1065
+ content: '';
1066
+ display: block;
1067
+ width: 10px;
1068
+ height: 6px;
1069
+ background-color: #fff;
1070
+ clip-path: polygon(5% 0, 95% 0, 100% 15%, 55% 100%, 45% 100%, 0 15%);
1071
+ position: relative;
1072
+ left: 154px;
1073
+ transform: rotateZ(-90deg);
1074
+ top: -12px;
1075
+ }
1076
+
1077
+ .image-item .art_set span::before {
1078
+ content: '';
1079
+ display: block;
1080
+ width: 10px;
1081
+ height: 6px;
1082
+ background-color: #fff;
1083
+ clip-path: polygon(5% 0, 95% 0, 100% 15%, 55% 100%, 45% 100%, 0 15%);
1084
+ position: relative;
1085
+ left: 6px;
1086
+ transform: rotateZ(90deg);
1087
+ top: 6px;
1088
+ margin-bottom: -6px;
1089
+ }
1090
+
1091
  .image-item .imgBox {
1092
  position: relative;
1093
  z-index: 0;
index.html CHANGED
@@ -34,14 +34,6 @@
34
  <span class="link" id="sortTA">🔠</span>
35
  </div>
36
  <div class="divider"></div>
37
- <div id="second_model">
38
- <span>B:</span><div>
39
- <select onautocomplete="off">
40
- <option value="SDXL">2nd model: SDXL 1.0</option>
41
- </select>
42
- </div>
43
- </div>
44
- <div class="divider"></div>
45
  <label class="top_control top_all">
46
  <input type="checkbox" checked="checked" name="check-all" value="check-all" autocomplete="off"><span>all artists</span><span class="count"></span>
47
  </label>
@@ -62,7 +54,7 @@
62
  <input type="checkbox" checked="checked" name="deprecated" value="deprecated" autocomplete="off"><span>hide unknown to SDXL</span><span class="count"></span>
63
  </label>
64
  <label class="top_control">
65
- <input type="checkbox" checked="checked" name="nudity" value="nudity" autocomplete="off"><span>don't blur risqué</span><span class="count"></span>
66
  </label>
67
  <div class="divider"></div>
68
  <span id="edit_most_used" class="hidden">edit these</span>
@@ -192,13 +184,25 @@
192
  <li><strong>⭐️</strong> to toggle them as favorited</li>
193
  <li><strong>🌐</strong> Web search for the artist</li>
194
  <li><strong>🎨🧑🏞️</strong> rotate between the 3 prompts</li>
195
- <li><strong>model</strong> switch between vanilla SDXL (A) and another model (B)</li>
196
  </ul>
197
- <h3>B: Model</h3>
198
  <ul>
199
- <li>Allows you to select a second XL model (B) to compare with the vanilla XL model from Stability (A).
200
- Switch between A and B by tapping the matching button on an artist.</li>
201
- <li>These models were selected by me based on what I prefer. I have no relationship with these model makers.</li>
 
 
 
 
 
 
 
 
 
 
 
 
202
  <li><strong>DynaVision:</strong>
203
  <ul>
204
  <li>Makes cute faces, removes artifacts, saturates colors, while preserving artist style.</li>
@@ -206,6 +210,7 @@
206
  <li>For landscapes, it reduces artist style strongly but improves composition.</li>
207
  <li>Improves anatomy and leans towards NSFW. Proportions are somewhat cartoonish.</li>
208
  <li>To remove the "big eyes" effect, use "anime" in the negative prompt.</li>
 
209
  </ul>
210
  </li>
211
  <li><strong>Crystal Clear:</strong>
@@ -213,6 +218,7 @@
213
  <li>Adds detail and removes artifacts while while strongly preserving artist style.</li>
214
  <li>Preserves styles even for landscapes and even for messy/grungy artists.</li>
215
  <li>Makes faces more aesthetic, improves anatomy, and leans towards realism.</li>
 
216
  </ul>
217
  </li>
218
  </ul>
@@ -233,9 +239,9 @@
233
  <li>If you prompt with their names, the result will be unlike their actual style and generic, and you can achieve similar results by prompting "a painting", etc.</li>
234
  <li>They're included in the database for the record of what SDXL doesn't know</li>
235
  </ul>
236
- <h3>Don't blur risqué</h3>
237
  <ul>
238
- <li>Risqué means any image that isn't G-rated and 100% SFW by extremely conservative standards. But the most risqué this site gets is images with boobies.</li>
239
  </ul>
240
  <h3>Important tags</h3>
241
  <ul>
@@ -258,10 +264,12 @@
258
  The prompt used for the 🎨 images is the intentionally generic, "an image". If that results in a portrait, that's useful to know. It indicates that, for that artist, SDXL is more strongly trained to output portraits. Anything in your prompt that's not related to a person will harder to prompt for in that artist's style.
259
  </li>
260
  </ul>
261
- <h3>✍️ Offline tag-editing mode</h3>
 
262
  <ul>
263
  <li>This feature is only for editing tags offline. If you are viewing this from Hugging Face, any tag edits won't be applied, but they'll be saved. If you've downloaded the repository and are viewing your local file, tag edits are applied. In both cases, your edits will be available for export 📥 as text. If you want to suggest tag improvements for everyone's benefit, edit tags, copy the text from 📥, and post it as a comment to Hugging Face. I will incorporate accurate edits ASAP. Thank you for contributing!</li>
264
  </ul>
 
265
  </div>
266
  </div>
267
  <div id="information_tips" class="information_section">
@@ -335,7 +343,7 @@
335
  <ul>
336
  <li>
337
  <strong>All:</strong><br>
338
- Steps: 20, Sampler: DPM++ 2M Karras, CFG scale: 5, Seed: 47, Size: 1024x1024, Model hash: 31e35c80fc, Model: sd_xl_base_1.0, Version: v1.5.1, <strong>(refiner not used)</strong>
339
  </li>
340
  <li>
341
  <strong>🎨 prompt:</strong><br>
@@ -361,14 +369,14 @@
361
  </ul>
362
  <h3>Disclaimers</h3>
363
  <ul>
364
- <li>The tags are mostly my manual input, with a mix of other sources including AI. They may be incorrect!</li>
365
- <li>SDXL is only a crude imitation of these artists. Check out these artists' actual artwork for more inspiration!</li>
366
- <li>This database has more straight white male artists than in the actual population. That's because they've been favored by art-collectors, past and present. Please suggest non white male artists that I should add.</li>
367
  <li>My code doesn't use cookies, and it sends nothing to any server. But it's hosted on Hugging Face, and I can't control if they cookie you.</li>
368
- <li>This tool is open source and Creatives Commons license. Download for free, use offline, modify as you wish.</li>
369
  <li>I don't get, nor do I want, any compensation for this. Getting thanked feels great though!</li>
370
- <li>I'm not affiliated with Stability AI or any model makers.</li>
371
- <li>This tools is only for fun. Use at your own risk. You're responsible for your own actions. Void where prohibited.</li>
372
  </ul>
373
  </div>
374
  </div>
 
34
  <span class="link" id="sortTA">🔠</span>
35
  </div>
36
  <div class="divider"></div>
 
 
 
 
 
 
 
 
37
  <label class="top_control top_all">
38
  <input type="checkbox" checked="checked" name="check-all" value="check-all" autocomplete="off"><span>all artists</span><span class="count"></span>
39
  </label>
 
54
  <input type="checkbox" checked="checked" name="deprecated" value="deprecated" autocomplete="off"><span>hide unknown to SDXL</span><span class="count"></span>
55
  </label>
56
  <label class="top_control">
57
+ <input type="checkbox" name="censored" value="censored" autocomplete="off"><span>show risqué images</span><span class="count"></span>
58
  </label>
59
  <div class="divider"></div>
60
  <span id="edit_most_used" class="hidden">edit these</span>
 
184
  <li><strong>⭐️</strong> to toggle them as favorited</li>
185
  <li><strong>🌐</strong> Web search for the artist</li>
186
  <li><strong>🎨🧑🏞️</strong> rotate between the 3 prompts</li>
187
+ <li><strong>image set</strong> rotate between 4 image sets</li>
188
  </ul>
189
+ <h3>The image sets</h3>
190
  <ul>
191
+ <li><strong>SDXL 1.0 model from StabilityAI:</strong>
192
+ <ul>
193
+ <li>As the base model, 1.0 preserves all artist styles better than any other fine tune.</li>
194
+ <li>Also has more diversity that any other model, except for anatomy.</li>
195
+ <li>The trade-off is that it's less aesthetic and causes more artifacts.</li>
196
+ </ul>
197
+ </li>
198
+ <li><strong>The artists' actual artwork:</strong>
199
+ <ul>
200
+ <li>These images weren't generated by any SDXL model.</li>
201
+ <li>These are screenshots of the artists' work available on the public web.</li>
202
+ <li>I believe these tiny thumbnails are educational fair use.</li>
203
+ <li>If you own any image and want it removed, please message me.</li>
204
+ </ul>
205
+ </li>
206
  <li><strong>DynaVision:</strong>
207
  <ul>
208
  <li>Makes cute faces, removes artifacts, saturates colors, while preserving artist style.</li>
 
210
  <li>For landscapes, it reduces artist style strongly but improves composition.</li>
211
  <li>Improves anatomy and leans towards NSFW. Proportions are somewhat cartoonish.</li>
212
  <li>To remove the "big eyes" effect, use "anime" in the negative prompt.</li>
213
+ <li>I have no relationship with the makers of this model.</li>
214
  </ul>
215
  </li>
216
  <li><strong>Crystal Clear:</strong>
 
218
  <li>Adds detail and removes artifacts while while strongly preserving artist style.</li>
219
  <li>Preserves styles even for landscapes and even for messy/grungy artists.</li>
220
  <li>Makes faces more aesthetic, improves anatomy, and leans towards realism.</li>
221
+ <li>I have no relationship with the makers of this model.</li>
222
  </ul>
223
  </li>
224
  </ul>
 
239
  <li>If you prompt with their names, the result will be unlike their actual style and generic, and you can achieve similar results by prompting "a painting", etc.</li>
240
  <li>They're included in the database for the record of what SDXL doesn't know</li>
241
  </ul>
242
+ <h3>Show risqué images</h3>
243
  <ul>
244
+ <li>You can blur out all images that aren't G-rated and 100% SFW by extremely conservative standards. This app contains now X-rated or hardcore images.</li>
245
  </ul>
246
  <h3>Important tags</h3>
247
  <ul>
 
264
  The prompt used for the 🎨 images is the intentionally generic, "an image". If that results in a portrait, that's useful to know. It indicates that, for that artist, SDXL is more strongly trained to output portraits. Anything in your prompt that's not related to a person will harder to prompt for in that artist's style.
265
  </li>
266
  </ul>
267
+ <!--
268
+ <h3>✍️ Offline tag-editing mode</h3>
269
  <ul>
270
  <li>This feature is only for editing tags offline. If you are viewing this from Hugging Face, any tag edits won't be applied, but they'll be saved. If you've downloaded the repository and are viewing your local file, tag edits are applied. In both cases, your edits will be available for export 📥 as text. If you want to suggest tag improvements for everyone's benefit, edit tags, copy the text from 📥, and post it as a comment to Hugging Face. I will incorporate accurate edits ASAP. Thank you for contributing!</li>
271
  </ul>
272
+ -->
273
  </div>
274
  </div>
275
  <div id="information_tips" class="information_section">
 
343
  <ul>
344
  <li>
345
  <strong>All:</strong><br>
346
+ Steps: 20, Sampler: DPM++ 2M Karras, CFG scale: 5, Seed: 47, Size: 1024x1024, <strong>(refiner not used)</strong>
347
  </li>
348
  <li>
349
  <strong>🎨 prompt:</strong><br>
 
369
  </ul>
370
  <h3>Disclaimers</h3>
371
  <ul>
372
+ <li>I believe the purpose of art is to share ideas and to inspire. New art is only possible by imitating and remixing old art. SDXL and this app promote art, inspire, and educate. For now, AI can only crudely imitate each artist. I encourage you to explore the real artwork and history of each artist you enjoy.</li>
373
+ <li>To create the tags, I've used a mix of LLM lots of manual research and edits. But the tags may be incorrect! Let me know if you have any corrections.</li>
374
+ <li>This database has a larger proportion of straight white male artists than the actual population. That's because, in the past and present, woman and minorities have had fewer opportunities to devote time to and sell their artwork. Please suggest under-represented artists that I can add to this app.</li>
375
  <li>My code doesn't use cookies, and it sends nothing to any server. But it's hosted on Hugging Face, and I can't control if they cookie you.</li>
376
+ <li>This app is open source and Creatives Commons license. Download for free, use offline, modify as you wish.</li>
377
  <li>I don't get, nor do I want, any compensation for this. Getting thanked feels great though!</li>
378
+ <li>I'm not affiliated with Stability AI, any model makers, or any organization.</li>
379
+ <li>This app is only for fun and education. Use at your own risk. You're responsible for your own actions. Void where prohibited.</li>
380
  </ul>
381
  </div>
382
  </div>
index.js CHANGED
@@ -6,15 +6,18 @@
6
  var p1 = performance.now();
7
  var timer;
8
  var artTypes = ['🎨','🧑','🏞️'];
 
9
  var artTitles = ['artwork','portraits','landscapes'];
10
  var models = [
11
  // path, short display name, full display name
12
- ['SDXL_1_0','SDXL 1.0','SDXL 1.0 Stability.ai official'],
13
- ['SDXL_DynaVision','XL DynaVision','SDXL DynaVision beta v0.4.1.1'],
14
- ['SDXL_Crystal_Clear','XL CrystalClr','Crystal Clear XL vCCXL'],
 
 
 
15
  ];
16
- var secondModelIsSelected = false;
17
- var secondModelSelected = 1;
18
  var initialPosX = -1;
19
  var initialPosY = -1;
20
  var prevScrollTop = -1; // used for lazyLoad
@@ -38,7 +41,7 @@ var missingFiles = '';
38
  var promptStyleWords = ['artwork in the style of','by|||']
39
  const lowCountThreshold = 3;
40
  const unloadedImgSrc = 'data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoBAAEAAkA4JaQAA3AA/vgfgAA='; // a 1x1 pixel
41
- const maxAristsToBeLoaded = 50; // each artist has 6 images, 3 per model
42
  const artistLoadingChunk = 15; // artists loaded per lazy load call
43
  const missingInterval = setInterval(checkMissingInterval, 5000);
44
  var imageItemUnloadQueue = [];
@@ -58,19 +61,18 @@ async function startUp() {
58
  makeConcatenatedTagSet();
59
  await loadEditedArtists();
60
  insertArtists();
61
- insertModels();
62
  insertCheckboxesFromArtistsData();
63
  insertCheckboxesFromCategories();
64
  await loadCheckboxesState();
65
  showHideCategories();
66
  await loadOptionsState();
67
  await loadFavoritesState();
68
- blurUnblurNudity();
69
  hideAllArtists();
70
  unhideBasedOnPermissiveSetting();
71
  sortArtists();
72
  rotatePromptsImages();
73
- updateArtistsImgSrc(false,false);
74
  updateTags('start');
75
  makeStyleRuleForDrag();
76
  // teasePartition();
@@ -333,7 +335,7 @@ function insertArtists() {
333
  //
334
  var artSearch = document.createElement('a');
335
  artSearch.className = 'art_search';
336
- artSearch.href = 'https://duckduckgo.com/?iax=images&ia=images&q=' + artist[1].replace(' ','+') + '+' + artist[0].replace(' ','+') + '+artist';
337
  artSearch.target = '_blank';
338
  artSearch.title = 'Web image search';
339
  var artSearchSpan = document.createElement('span');
@@ -344,7 +346,7 @@ function insertArtists() {
344
  var artSet = document.createElement('div');
345
  artSet.className = 'art_set';
346
  var artSetSpan = document.createElement('span');
347
- artSetSpan.textContent = 'A: ' + models[0][1];
348
  artSetSpan.title = 'showing ' + models[0][2];
349
  artSet.appendChild(artSetSpan);
350
  imgTools.appendChild(artSet);
@@ -352,7 +354,6 @@ function insertArtists() {
352
  holder.appendChild(imgTools);
353
  var imgBox0 = document.createElement('div');
354
  imgBox0.className = 'imgBox';
355
- imgBox0.dataset.model = 0;
356
  var imgArtwork = document.createElement('img');
357
  var imgPortrait = document.createElement('img');
358
  var imgLandscape = document.createElement('img');
@@ -376,12 +377,6 @@ function insertArtists() {
376
  imgBox0.appendChild(modelName);
377
  holder.appendChild(imgBox0);
378
  //
379
- let imgBox1 = imgBox0.cloneNode(true);
380
- imgBox1.classList.add('hidden');
381
- imgBox1.dataset.model = 1;
382
- imgBox1.querySelector('.model_name span').childNodes[2].nodeValue = models[secondModelSelected][2];
383
- holder.appendChild(imgBox1);
384
- //
385
  if(artist[3]) {
386
  itemDiv.dataset.deprecated = true;
387
  var deprecatedSpan = document.createElement('span');
@@ -421,7 +416,7 @@ function getArtistsByDistanceFromMiddle() {
421
  return imageItemsVisible;
422
  }
423
 
424
- function updateArtistsImgSrc(filteredImageItems,onlySecondModel) {
425
  if(filteredImageItems == false) {
426
  // initial page load
427
  filteredImageItems = getArtistsByDistanceFromMiddle();
@@ -433,38 +428,24 @@ function updateArtistsImgSrc(filteredImageItems,onlySecondModel) {
433
  // load those artists (update the image src)
434
  let imagePromises = [];
435
  filteredImageItems.forEach(function(item){
436
- let src0 = 'images/' + models[0][0] + '_thumbs/';
437
- let src1 = 'images/' + models[secondModelSelected][0] + '_thumbs/';
438
  let firstN = item.querySelector('.firstN').textContent;
439
  let lastN = item.querySelector('.lastN').textContent;
440
  // files use accented characters and huggingface stores the files with this encoding
441
  src0 = encodeURI(src0.normalize("NFD"));
442
- src1 = encodeURI(src1.normalize("NFD"));
443
  if(firstN == '') {
444
  src0 += lastN.replaceAll(' ', '_');
445
- src1 += lastN.replaceAll(' ', '_');
446
  } else {
447
  src0 += firstN.replaceAll(' ', '_') + '_' + lastN.replaceAll(' ', '_');
448
- src1 += firstN.replaceAll(' ', '_') + '_' + lastN.replaceAll(' ', '_');
449
  }
450
  //
451
- let imgAlt0 = 'artist: ' + firstN + ' ' + lastN + ' - model: ' + models[0][1];
452
- let imgAlt1 = 'artist: ' +firstN + ' ' + lastN + ' - model: ' + models[secondModelSelected][1];
453
  //
454
- let imgBox0 = item.querySelector('.imgBox[data-model="0"]');
455
- let imgBox1 = item.querySelector('.imgBox[data-model="1"]');
456
- delete imgBox1.querySelector('.img_artwork').dataset.thumbSrc;
457
- delete imgBox1.querySelector('.img_portrait').dataset.thumbSrc;
458
- delete imgBox1.querySelector('.img_landscape').dataset.thumbSrc;
459
  let imgArray = [];
460
- if(!onlySecondModel) {
461
- imgArray.push([imgBox0.querySelector('.img_artwork'), src0 + '-artwork.webp', imgAlt0 + ' - prompt: artwork']);
462
- imgArray.push([imgBox0.querySelector('.img_portrait'), src0 + '-portrait.webp', imgAlt0 + ' - prompt: portrait']);
463
- imgArray.push([imgBox0.querySelector('.img_landscape'), src0 + '-landscape.webp', imgAlt0 + ' - prompt: landscape']);
464
- }
465
- imgArray.push([imgBox1.querySelector('.img_artwork'), src1 + '-artwork.webp', imgAlt1 + ' - prompt: artwork']);
466
- imgArray.push([imgBox1.querySelector('.img_portrait'), src1 + '-portrait.webp', imgAlt1 + ' - prompt: portrait']);
467
- imgArray.push([imgBox1.querySelector('.img_landscape'), src1 + '-landscape.webp', imgAlt1 + ' - prompt: landscape']);
468
  //
469
  generateUnloadQueue();
470
  imgArray.forEach(function(imgDetails) {
@@ -472,23 +453,21 @@ function updateArtistsImgSrc(filteredImageItems,onlySecondModel) {
472
  imgDetails[0].src = imgDetails[1];
473
  imgDetails[0].alt = imgDetails[2];
474
  if(imgDetails[0].complete) {
475
- if(imgDetails[0].classList.contains('img_artwork') &&
476
- imgDetails[0].closest('.imgBox').dataset.model == '0') {
477
  lazyUnloadOne();
478
  }
479
  resolve();
480
  return;
481
  }
482
- imgDetails[0].onload = (img) => {
483
- if(imgDetails[0].classList.contains('img_artwork') &&
484
- imgDetails[0].closest('.imgBox').dataset.model == '0') {
485
  lazyUnloadOne();
486
  }
487
  imgDetails[0].onload = null;
488
  imgDetails[0].onerror = null;
489
  resolve();
490
  };
491
- imgDetails[0].onerror = (img) => {
492
  missingFiles += imgDetails[1] + '\n';
493
  imgDetails[0].onload = null;
494
  imgDetails[0].onerror = null;
@@ -499,7 +478,7 @@ function updateArtistsImgSrc(filteredImageItems,onlySecondModel) {
499
  });
500
  });
501
  Promise.allSettled(imagePromises).then(() => {
502
- });
503
  }
504
 
505
  function lazyLoad() {
@@ -561,7 +540,7 @@ function lazyLoad() {
561
  i++;
562
  }
563
  // slice to a chunk-size and load
564
- updateArtistsImgSrc(itemsToBeLoaded,false);
565
  }
566
  prevScrollTop = currentScrollTop;
567
  }
@@ -610,32 +589,6 @@ function lazyUnloadOne() {
610
  }
611
  }
612
 
613
- function insertModels() {
614
- let secondModelSelector = document.querySelector('#second_model select');
615
- secondModelSelector.innerHTML = '';
616
- for (var i=1, il=models.length; i<il; i++) {
617
- // model 0 is the primary model
618
- let model = models[i];
619
- let option = document.createElement('option');
620
- option.value = model[0];
621
- option.textContent = model[1];
622
- secondModelSelector.appendChild(option);
623
- }
624
- }
625
-
626
- function setSecondModelSelected(select) {
627
- for(i=0,il=models.length; i<il; i++) {
628
- if(models[i][0] === select.value) {
629
- secondModelSelected = i;
630
- break;
631
- }
632
- }
633
- secondModelIsSelected = false;
634
- rotateModelsImages();
635
- // update images (but only second model)
636
- updateArtistsImgSrc(false,true);
637
- }
638
-
639
  function insertCheckboxesFromArtistsData() {
640
  var uniqueTags = new Set();
641
  artistsData.forEach(function(artist) {
@@ -713,7 +666,7 @@ async function loadCheckboxesState() {
713
  && name != 'use_categories'
714
  && name != 'low_count'
715
  && name != 'deprecated'
716
- && name != 'nudity') {
717
  if(!state[name]) {
718
  allChecked = false;
719
  }
@@ -800,24 +753,48 @@ function highlightSelectedOption(selected) {
800
  });
801
  if(imgTypeShown == 0) {
802
  document.getElementById('promptA').classList.add('selected');
803
- doAlert('Showing artwork',0);
 
 
 
 
804
  } else if(imgTypeShown == 1) {
805
  document.getElementById('promptP').classList.add('selected');
806
- doAlert('Showing portraits',0);
 
 
 
 
807
  } else if(imgTypeShown == 2) {
808
  document.getElementById('promptL').classList.add('selected');
809
- doAlert('Showing landscapes',0);
 
 
 
 
810
  }
811
  } else {
812
  if(selected == 'promptA') {
813
  imgTypeShown = 0;
814
- doAlert('Showing artwork',0);
 
 
 
 
815
  } else if(selected == 'promptP') {
816
  imgTypeShown = 1;
817
- doAlert('Showing portraits',0);
 
 
 
 
818
  } else if(selected == 'promptL') {
819
  imgTypeShown = 2;
820
- doAlert('Showing landscapes',0);
 
 
 
 
821
  }
822
  var links = document.getElementById(selected).parentNode.querySelectorAll('.link');
823
  links.forEach(function(link) {
@@ -867,53 +844,71 @@ function rotatePromptsImages() {
867
  image.classList.remove('hidden');
868
  });
869
  // switch prev and next button icons
 
 
 
 
 
870
  let prevButtons = document.querySelectorAll('.art_prev span');
871
  prevButtons.forEach(function(span) {
872
- span.textContent = artTypes[imgTypeShown];
873
  span.title = 'showing ' + artTitles[imgTypeShown];
874
  });
875
  let nextButtons = document.querySelectorAll('.art_next span');
876
  nextButtons.forEach(function(span) {
877
- span.textContent = artTypes[imgTypeShown];
878
  span.title = 'showing ' + artTitles[imgTypeShown];
879
  });
880
  }
881
 
882
- function rotateModelsImages() {
883
- // hide all imgBoxes
884
- let visibleImgBoxes = document.querySelectorAll('.imgBox:not(.hidden)');
885
- visibleImgBoxes.forEach(function(imgBox) {
886
- imgBox.classList.add('hidden');
887
- });
888
- // switch model selection, unhide desired imgBox
889
- if(secondModelIsSelected) {
890
- secondModelIsSelected = false;
891
- visibleImgBoxes = document.querySelectorAll('.imgBox[data-model="0"]');
892
- } else {
893
- secondModelIsSelected = true;
894
- visibleImgBoxes = document.querySelectorAll('.imgBox[data-model="1"]');
895
  }
896
- visibleImgBoxes.forEach(function(imgBox) {
897
- imgBox.classList.remove('hidden');
898
- });
899
- // update button
900
  let artSetSpans = document.querySelectorAll('.art_set span');
901
  artSetSpans.forEach(function(span) {
902
- if(secondModelIsSelected) {
903
- span.textContent = 'B: ' + models[secondModelSelected][1];
904
- span.title = 'showing ' + models[secondModelSelected][2];
905
- doAlert('Showing B: ' + models[secondModelSelected][1],0);
906
- } else {
907
- span.textContent = 'A: ' + models[0][1];
908
- span.title = 'showing ' + models[0][2];
909
- doAlert('Showing A:' + models[0][1],0);
910
- }
911
  });
912
- // update name shown on hover
913
  let modelName = document.querySelectorAll('.model_name span');
914
  modelName.forEach(function(span) {
915
- span.childNodes[2].nodeValue = models[secondModelSelected][2];
 
 
 
 
 
916
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
917
  }
918
 
919
  function updateTags(whoCalled) {
@@ -1119,28 +1114,26 @@ function checkAllInCategory(theCheckbox) {
1119
  }
1120
  }
1121
 
1122
- function blurUnblurNudity() {
1123
- let nudity = document.querySelector('input[name="nudity"]');
1124
- if(nudity.checked) {
1125
- nudity.parentNode.classList.remove('warning');
1126
- let images = document.querySelectorAll('.img');
1127
- images.forEach(function(img){
1128
- img.classList.remove('censored');
1129
- });
1130
  } else {
1131
- nudity.parentNode.classList.add('warning');
1132
  for (let i=0, il=artistsData.length; i<il; i++) {
1133
  let artist = artistsData[i];
1134
  for(j=0,jl=artist[4].length; j<jl; j++) {
1135
- let blurBox = 0;
1136
  let blurModel = artist[4][j][0];
1137
- // blurModel index matches models[]
1138
- if(blurModel > 0) { blurBox = 1; }
1139
  let blurImage = artist[4][j][1];
1140
  if(blurImage == 'a') { blurImage = '.img_artwork'; }
1141
  if(blurImage == 'p') { blurImage = '.img_portrait'; }
1142
  if(blurImage == 'l') { blurImage = '.img_landscape'; }
1143
- if(blurModel == secondModelSelected || blurModel == 0) {
1144
  let imageItems = document.querySelectorAll('.image-item');
1145
  for(k=0,kl=imageItems.length; k<kl; k++) {
1146
  // find match in artistsData if first and last names match
@@ -1148,7 +1141,7 @@ function blurUnblurNudity() {
1148
  let firstN = imageItem.querySelector('.firstN').textContent;
1149
  let lastN = imageItem.querySelector('.lastN').textContent;
1150
  if(artist[0] == lastN && artist[1] == firstN) {
1151
- let box = imageItem.querySelector('.imgBox[data-model="' + blurBox + '"');
1152
  let image = box.querySelector(blurImage).classList.add('censored');
1153
  break;
1154
  }
@@ -1160,20 +1153,19 @@ function blurUnblurNudity() {
1160
  }
1161
 
1162
  function toggleCensored(h4) {
 
1163
  let imageItem = h4.closest('.image-item');
1164
  let firstN = imageItem.querySelector('.firstN').textContent;
1165
  let lastN = imageItem.querySelector('.lastN').textContent;
1166
  for (let i=0, il=artistsData.length; i<il; i++) {
1167
  let artist = artistsData[i];
1168
  if(artist[0] == lastN && artist[1] == firstN) {
1169
- let blurModel = imageItem.querySelector('.imgBox:not(.hidden)').dataset.model;
1170
- if(blurModel == 1) { blurModel = secondModelSelected; }
1171
  let img = imageItem.querySelector('.imgBox:not(.hidden) .img:not(.hidden)');
1172
  let blurImage = '';
1173
  if(img.classList.contains('img_artwork')) { blurImage = 'a'; }
1174
  if(img.classList.contains('img_portrait')) { blurImage = 'p'; }
1175
  if(img.classList.contains('img_landscape')) { blurImage = 'l'; }
1176
- let blurNew = blurModel + blurImage;
1177
  let match = false;
1178
  for(j=0,jl=artist[4].length; j<jl; j++) {
1179
  let blurOld = artist[4][j]
@@ -2087,8 +2079,10 @@ function copyStuffToClipboard(item,stuff) {
2087
  });
2088
  for(i=0,il=imageItemsArr.length;i<il;i++) {
2089
  let item = imageItemsArr[i];
2090
- str += item.querySelectorAll('h3 span')[0].textContent + ' ';
2091
- str += item.querySelectorAll('h3 span')[1].textContent + '\n';
 
 
2092
  count++;
2093
  }
2094
  if(count > 0) {
@@ -2117,6 +2111,7 @@ function copyStuffToClipboard(item,stuff) {
2117
  }
2118
 
2119
  function toggleThisArtistsTags(tagsStr) {
 
2120
  let names = tagsStr.split(', ');
2121
  let allChecked = true;
2122
  for(i=0,il=names.length;i<il;i++) {
@@ -2209,13 +2204,8 @@ function showLargerImages(imageItem) {
2209
  let first = img.closest('.image-item').querySelector('.firstN').textContent;
2210
  let last = img.closest('.image-item').querySelector('.lastN').textContent;
2211
  img.dataset.thumbSrc = img.src;
2212
- let model = img.closest('.imgBox').dataset.model;
2213
  let src = 'images/'
2214
- if(model == 0) {
2215
- src += models[0][0] + '/';
2216
- } else {
2217
- src += models[secondModelSelected][0] + '/';
2218
- }
2219
  if(first == '') {
2220
  src += last.replaceAll(' ', '_');
2221
  } else {
@@ -3023,6 +3013,21 @@ function debouncer(func, delay) {
3023
  };
3024
  }
3025
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3026
  /*
3027
  **
3028
  **
@@ -3045,16 +3050,16 @@ function debouncer(func, delay) {
3045
 
3046
  function addAllListeners() {
3047
  // global
3048
- document.addEventListener('keydown', function(event) {
3049
- if(event.key === 'Escape' || event.keyCode === 27) {
3050
  // event.key for modern browsers, event.keyCode for older ones
3051
  enterExitEditMostUsedMode('exit');
3052
  editTagsFindArtistInEditMode();
3053
  hideInfo();
3054
  }
3055
  });
3056
- document.addEventListener('keyup', function(event) {
3057
- if(event.key === '/') {
3058
  showInfo();
3059
  showInformation('actions');
3060
  }
@@ -3112,9 +3117,9 @@ function addAllListeners() {
3112
  unhideBasedOnPermissiveSetting();
3113
  updateTags('click');
3114
  });
3115
- } else if(checkbox.name == 'nudity') {
3116
  checkbox.addEventListener('change', function(e) {
3117
- blurUnblurNudity();
3118
  });
3119
  }
3120
  }
@@ -3124,8 +3129,8 @@ function addAllListeners() {
3124
  clearSelection();
3125
  storeCheckboxState(e.target);
3126
  window.setTimeout(function() {
3127
- updateArtistsImgSrc(false,false);
3128
- })
3129
  });
3130
  });
3131
  // information
@@ -3239,8 +3244,8 @@ function addAllListeners() {
3239
  sortAA.addEventListener('click', function(e) {
3240
  sortArtistsByAlpha();
3241
  window.setTimeout(function() {
3242
- updateArtistsImgSrc(false,false);
3243
- })
3244
  highlightSelectedOption('sortAA');
3245
  storeOptionsState();
3246
  });
@@ -3248,17 +3253,11 @@ function addAllListeners() {
3248
  sortAR.addEventListener('click', function(e) {
3249
  sortArtistsByRandom();
3250
  window.setTimeout(function() {
3251
- updateArtistsImgSrc(false,false);
3252
- })
3253
  highlightSelectedOption('sortAR');
3254
  storeOptionsState();
3255
  });
3256
- // second model selector
3257
- let secondModelSelector = document.querySelector('#second_model select');
3258
- secondModelSelector.addEventListener('change', function(e) {
3259
- setSecondModelSelected(this);
3260
- blurUnblurNudity();
3261
- });
3262
 
3263
  // most used mode
3264
  var mostUsed = document.getElementById('edit_most_used');
@@ -3313,9 +3312,20 @@ function addAllListeners() {
3313
  imageItem.querySelector('.art_edit').addEventListener('click', function(e) {
3314
  editTagsClicked(this.closest('.image-item'));
3315
  });
3316
- imageItem.querySelector('.art_set').addEventListener('click', function() {
3317
- rotateModelsImages();
3318
- blurUnblurNudity();
 
 
 
 
 
 
 
 
 
 
 
3319
  });
3320
  imageItem.getElementsByTagName('h3')[0].addEventListener('click', function(e) {
3321
  copyStuffToClipboard(this,'name');
@@ -3324,8 +3334,6 @@ function addAllListeners() {
3324
  imageItem.getElementsByTagName('h4')[0].addEventListener('click', function(e) {
3325
  if(!this.classList.contains('edit_mode')) {
3326
  copyStuffToClipboard(this, 'tags')
3327
- // toggleCensored(this);
3328
- // toggleThisArtistsTags(this.textContent);
3329
  }
3330
  });
3331
  });
@@ -3336,7 +3344,7 @@ function addAllListeners() {
3336
  gutterStartPosX = this.offsetLeft;
3337
  mouseStartPosX = e.pageX;
3338
  this.addEventListener('mousemove', movePartition, false);
3339
- window.addEventListener('mouseup', function() {
3340
  gutter.removeEventListener('mousemove', movePartition, false);
3341
  }, false);
3342
  }, false);
@@ -3359,12 +3367,12 @@ function addAllListeners() {
3359
  promptBuilderAddArtist();
3360
  });
3361
  var prompt_selector_div = document.querySelector('#prompt_selector > div');
3362
- prompt_selector_div.addEventListener('scroll', debouncer(function() {
3363
  setXPosOfSearchOutput();
3364
  }, 100));
3365
  // lazy loader
3366
  var rows = document.querySelector('#rows');
3367
- rows.addEventListener('scroll', debouncer(function() {
3368
  lazyLoad();
3369
  }, 50));
3370
- }
 
6
  var p1 = performance.now();
7
  var timer;
8
  var artTypes = ['🎨','🧑','🏞️'];
9
+ var artTypesAlt = ['1️⃣','2️⃣','3️⃣'];
10
  var artTitles = ['artwork','portraits','landscapes'];
11
  var models = [
12
  // path, short display name, full display name
13
+ // short display name should have max of ~36 characters
14
+ // order here needs to match db for censoring function to work
15
+ ['SDXL_1_0','SDXL 1.0 Vanilla','SDXL 1.0 Stability.ai official'],
16
+ ['Ground_Truth','Actual artwork','Screenshots of the actual artwork'],
17
+ ['SDXL_Crystal_Clear','SDXL Crystal Clear','Crystal Clear XL vCCXL'],
18
+ ['SDXL_DynaVision','SDXL DynaVision','SDXL DynaVision beta v0.4.1.1'],
19
  ];
20
+ var modelSelected = 0;
 
21
  var initialPosX = -1;
22
  var initialPosY = -1;
23
  var prevScrollTop = -1; // used for lazyLoad
 
41
  var promptStyleWords = ['artwork in the style of','by|||']
42
  const lowCountThreshold = 3;
43
  const unloadedImgSrc = 'data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoBAAEAAkA4JaQAA3AA/vgfgAA='; // a 1x1 pixel
44
+ const maxAristsToBeLoaded = 40; // each artist loads 3 images
45
  const artistLoadingChunk = 15; // artists loaded per lazy load call
46
  const missingInterval = setInterval(checkMissingInterval, 5000);
47
  var imageItemUnloadQueue = [];
 
61
  makeConcatenatedTagSet();
62
  await loadEditedArtists();
63
  insertArtists();
 
64
  insertCheckboxesFromArtistsData();
65
  insertCheckboxesFromCategories();
66
  await loadCheckboxesState();
67
  showHideCategories();
68
  await loadOptionsState();
69
  await loadFavoritesState();
70
+ blurUnblurCensored();
71
  hideAllArtists();
72
  unhideBasedOnPermissiveSetting();
73
  sortArtists();
74
  rotatePromptsImages();
75
+ updateArtistsImgSrc(false);
76
  updateTags('start');
77
  makeStyleRuleForDrag();
78
  // teasePartition();
 
335
  //
336
  var artSearch = document.createElement('a');
337
  artSearch.className = 'art_search';
338
+ artSearch.href = 'https://duckduckgo.com/?ia=web&q=' + artist[1].replace(' ','+') + '+' + artist[0].replace(' ','+') + '+artist';
339
  artSearch.target = '_blank';
340
  artSearch.title = 'Web image search';
341
  var artSearchSpan = document.createElement('span');
 
346
  var artSet = document.createElement('div');
347
  artSet.className = 'art_set';
348
  var artSetSpan = document.createElement('span');
349
+ artSetSpan.textContent = models[0][1];
350
  artSetSpan.title = 'showing ' + models[0][2];
351
  artSet.appendChild(artSetSpan);
352
  imgTools.appendChild(artSet);
 
354
  holder.appendChild(imgTools);
355
  var imgBox0 = document.createElement('div');
356
  imgBox0.className = 'imgBox';
 
357
  var imgArtwork = document.createElement('img');
358
  var imgPortrait = document.createElement('img');
359
  var imgLandscape = document.createElement('img');
 
377
  imgBox0.appendChild(modelName);
378
  holder.appendChild(imgBox0);
379
  //
 
 
 
 
 
 
380
  if(artist[3]) {
381
  itemDiv.dataset.deprecated = true;
382
  var deprecatedSpan = document.createElement('span');
 
416
  return imageItemsVisible;
417
  }
418
 
419
+ function updateArtistsImgSrc(filteredImageItems) {
420
  if(filteredImageItems == false) {
421
  // initial page load
422
  filteredImageItems = getArtistsByDistanceFromMiddle();
 
428
  // load those artists (update the image src)
429
  let imagePromises = [];
430
  filteredImageItems.forEach(function(item){
431
+ let src0 = 'images/' + models[modelSelected][0] + '_thumbs/';
 
432
  let firstN = item.querySelector('.firstN').textContent;
433
  let lastN = item.querySelector('.lastN').textContent;
434
  // files use accented characters and huggingface stores the files with this encoding
435
  src0 = encodeURI(src0.normalize("NFD"));
 
436
  if(firstN == '') {
437
  src0 += lastN.replaceAll(' ', '_');
 
438
  } else {
439
  src0 += firstN.replaceAll(' ', '_') + '_' + lastN.replaceAll(' ', '_');
 
440
  }
441
  //
442
+ let imgAlt0 = 'artist: ' + firstN + ' ' + lastN + ' - model: ' + models[modelSelected][1];
 
443
  //
444
+ let imgBox0 = item.querySelector('.imgBox');
 
 
 
 
445
  let imgArray = [];
446
+ imgArray.push([imgBox0.querySelector('.img_artwork'), src0 + '-artwork.webp', imgAlt0 + ' - prompt: artwork']);
447
+ imgArray.push([imgBox0.querySelector('.img_portrait'), src0 + '-portrait.webp', imgAlt0 + ' - prompt: portrait']);
448
+ imgArray.push([imgBox0.querySelector('.img_landscape'), src0 + '-landscape.webp', imgAlt0 + ' - prompt: landscape']);
 
 
 
 
 
449
  //
450
  generateUnloadQueue();
451
  imgArray.forEach(function(imgDetails) {
 
453
  imgDetails[0].src = imgDetails[1];
454
  imgDetails[0].alt = imgDetails[2];
455
  if(imgDetails[0].complete) {
456
+ if(imgDetails[0].classList.contains('img_artwork')) {
 
457
  lazyUnloadOne();
458
  }
459
  resolve();
460
  return;
461
  }
462
+ imgDetails[0].onload = () => {
463
+ if(imgDetails[0].classList.contains('img_artwork')) {
 
464
  lazyUnloadOne();
465
  }
466
  imgDetails[0].onload = null;
467
  imgDetails[0].onerror = null;
468
  resolve();
469
  };
470
+ imgDetails[0].onerror = () => {
471
  missingFiles += imgDetails[1] + '\n';
472
  imgDetails[0].onload = null;
473
  imgDetails[0].onerror = null;
 
478
  });
479
  });
480
  Promise.allSettled(imagePromises).then(() => {
481
+ })
482
  }
483
 
484
  function lazyLoad() {
 
540
  i++;
541
  }
542
  // slice to a chunk-size and load
543
+ updateArtistsImgSrc(itemsToBeLoaded);
544
  }
545
  prevScrollTop = currentScrollTop;
546
  }
 
589
  }
590
  }
591
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
592
  function insertCheckboxesFromArtistsData() {
593
  var uniqueTags = new Set();
594
  artistsData.forEach(function(artist) {
 
666
  && name != 'use_categories'
667
  && name != 'low_count'
668
  && name != 'deprecated'
669
+ && name != 'censored') {
670
  if(!state[name]) {
671
  allChecked = false;
672
  }
 
753
  });
754
  if(imgTypeShown == 0) {
755
  document.getElementById('promptA').classList.add('selected');
756
+ if(modelSelected == 1) {
757
+ doAlert('Showing 1 of 3',0);
758
+ } else {
759
+ doAlert('Showing artwork',0);
760
+ }
761
  } else if(imgTypeShown == 1) {
762
  document.getElementById('promptP').classList.add('selected');
763
+ if(modelSelected == 1) {
764
+ doAlert('Showing 2 of 3',0);
765
+ } else {
766
+ doAlert('Showing portraits',0);
767
+ }
768
  } else if(imgTypeShown == 2) {
769
  document.getElementById('promptL').classList.add('selected');
770
+ if(modelSelected == 1) {
771
+ doAlert('Showing 3 of 3',0);
772
+ } else {
773
+ doAlert('Showing landscapes',0);
774
+ }
775
  }
776
  } else {
777
  if(selected == 'promptA') {
778
  imgTypeShown = 0;
779
+ if(modelSelected == 1) {
780
+ doAlert('Showing 1 of 3',0);
781
+ } else {
782
+ doAlert('Showing artwork',0);
783
+ }
784
  } else if(selected == 'promptP') {
785
  imgTypeShown = 1;
786
+ if(modelSelected == 1) {
787
+ doAlert('Showing 2 of 3',0);
788
+ } else {
789
+ doAlert('Showing portraits',0);
790
+ }
791
  } else if(selected == 'promptL') {
792
  imgTypeShown = 2;
793
+ if(modelSelected == 1) {
794
+ doAlert('Showing 3 of 3',0);
795
+ } else {
796
+ doAlert('Showing landscapes',0);
797
+ }
798
  }
799
  var links = document.getElementById(selected).parentNode.querySelectorAll('.link');
800
  links.forEach(function(link) {
 
844
  image.classList.remove('hidden');
845
  });
846
  // switch prev and next button icons
847
+ let whichArtTypeArray = artTypes;
848
+ if(modelSelected == 1) {
849
+ // the actual artwork
850
+ whichArtTypeArray = artTypesAlt;
851
+ }
852
  let prevButtons = document.querySelectorAll('.art_prev span');
853
  prevButtons.forEach(function(span) {
854
+ span.textContent = whichArtTypeArray[imgTypeShown];
855
  span.title = 'showing ' + artTitles[imgTypeShown];
856
  });
857
  let nextButtons = document.querySelectorAll('.art_next span');
858
  nextButtons.forEach(function(span) {
859
+ span.textContent = whichArtTypeArray[imgTypeShown];
860
  span.title = 'showing ' + artTitles[imgTypeShown];
861
  });
862
  }
863
 
864
+ function rotateModels(imageItem,direction) {
865
+ // update selected model
866
+ modelSelected += direction;
867
+ if(modelSelected == models.length) {
868
+ modelSelected = 0;
869
+ } else if(modelSelected < 0) {
870
+ modelSelected = models.length -1;
 
 
 
 
 
 
871
  }
872
+ // update model selector button
 
 
 
873
  let artSetSpans = document.querySelectorAll('.art_set span');
874
  artSetSpans.forEach(function(span) {
875
+ span.textContent = models[modelSelected][1];
876
+ span.title = 'showing ' + models[modelSelected][2];
877
+ doAlert('Showing: ' + models[modelSelected][1],0);
 
 
 
 
 
 
878
  });
879
+ // update name shown under the large hover image
880
  let modelName = document.querySelectorAll('.model_name span');
881
  modelName.forEach(function(span) {
882
+ span.childNodes[2].nodeValue = models[modelSelected][2];
883
+ });
884
+ // allow all images with large image src to be overwritten with new large image src
885
+ let images = document.querySelectorAll('.imgBox img');
886
+ images.forEach(function(img) {
887
+ delete img.dataset.thumbSrc;
888
  });
889
+ // update the prompt image buttons
890
+ let whichArtTypeArray = artTypes;
891
+ if(modelSelected == 1) {
892
+ // the actual artwork
893
+ whichArtTypeArray = artTypesAlt;
894
+ }
895
+ let prevButtons = document.querySelectorAll('.art_prev span');
896
+ prevButtons.forEach(function(span) {
897
+ span.textContent = whichArtTypeArray[imgTypeShown];
898
+ });
899
+ let nextButtons = document.querySelectorAll('.art_next span');
900
+ nextButtons.forEach(function(span) {
901
+ span.textContent = whichArtTypeArray[imgTypeShown];
902
+ });
903
+ // update the images async
904
+ timer = setTimeout(rotateModelsUpdate, 0, imageItem);
905
+ }
906
+
907
+ function rotateModelsUpdate(imageItem) {
908
+ updateArtistsImgSrc(false);
909
+ // has to be after the images switch, otherwise the previous images are briefly unblurred
910
+ blurUnblurCensored();
911
+ showLargerImages(imageItem);
912
  }
913
 
914
  function updateTags(whoCalled) {
 
1114
  }
1115
  }
1116
 
1117
+ function blurUnblurCensored() {
1118
+ let images = document.querySelectorAll('.img');
1119
+ images.forEach(function(img){
1120
+ img.classList.remove('censored');
1121
+ });
1122
+ let censored = document.querySelector('input[name="censored"]');
1123
+ if(censored.checked) {
1124
+ censored.parentNode.classList.remove('warning');
1125
  } else {
1126
+ censored.parentNode.classList.add('warning');
1127
  for (let i=0, il=artistsData.length; i<il; i++) {
1128
  let artist = artistsData[i];
1129
  for(j=0,jl=artist[4].length; j<jl; j++) {
1130
+ // blurModel index matches the order of models in models[]
1131
  let blurModel = artist[4][j][0];
 
 
1132
  let blurImage = artist[4][j][1];
1133
  if(blurImage == 'a') { blurImage = '.img_artwork'; }
1134
  if(blurImage == 'p') { blurImage = '.img_portrait'; }
1135
  if(blurImage == 'l') { blurImage = '.img_landscape'; }
1136
+ if(blurModel == modelSelected) {
1137
  let imageItems = document.querySelectorAll('.image-item');
1138
  for(k=0,kl=imageItems.length; k<kl; k++) {
1139
  // find match in artistsData if first and last names match
 
1141
  let firstN = imageItem.querySelector('.firstN').textContent;
1142
  let lastN = imageItem.querySelector('.lastN').textContent;
1143
  if(artist[0] == lastN && artist[1] == firstN) {
1144
+ let box = imageItem.querySelector('.imgBox');
1145
  let image = box.querySelector(blurImage).classList.add('censored');
1146
  break;
1147
  }
 
1153
  }
1154
 
1155
  function toggleCensored(h4) {
1156
+ // unused function
1157
  let imageItem = h4.closest('.image-item');
1158
  let firstN = imageItem.querySelector('.firstN').textContent;
1159
  let lastN = imageItem.querySelector('.lastN').textContent;
1160
  for (let i=0, il=artistsData.length; i<il; i++) {
1161
  let artist = artistsData[i];
1162
  if(artist[0] == lastN && artist[1] == firstN) {
 
 
1163
  let img = imageItem.querySelector('.imgBox:not(.hidden) .img:not(.hidden)');
1164
  let blurImage = '';
1165
  if(img.classList.contains('img_artwork')) { blurImage = 'a'; }
1166
  if(img.classList.contains('img_portrait')) { blurImage = 'p'; }
1167
  if(img.classList.contains('img_landscape')) { blurImage = 'l'; }
1168
+ let blurNew = modelSelected + blurImage;
1169
  let match = false;
1170
  for(j=0,jl=artist[4].length; j<jl; j++) {
1171
  let blurOld = artist[4][j]
 
2079
  });
2080
  for(i=0,il=imageItemsArr.length;i<il;i++) {
2081
  let item = imageItemsArr[i];
2082
+ let firstN = item.querySelectorAll('h3 span')[0].textContent;
2083
+ let lastN = item.querySelectorAll('h3 span')[1].textContent;
2084
+ if(firstN.length > 0) { firstN += ' '; }
2085
+ str += firstN + lastN + '\n';
2086
  count++;
2087
  }
2088
  if(count > 0) {
 
2111
  }
2112
 
2113
  function toggleThisArtistsTags(tagsStr) {
2114
+ // unused function
2115
  let names = tagsStr.split(', ');
2116
  let allChecked = true;
2117
  for(i=0,il=names.length;i<il;i++) {
 
2204
  let first = img.closest('.image-item').querySelector('.firstN').textContent;
2205
  let last = img.closest('.image-item').querySelector('.lastN').textContent;
2206
  img.dataset.thumbSrc = img.src;
 
2207
  let src = 'images/'
2208
+ src += models[modelSelected][0] + '/';
 
 
 
 
2209
  if(first == '') {
2210
  src += last.replaceAll(' ', '_');
2211
  } else {
 
3013
  };
3014
  }
3015
 
3016
+ function rotateModelDirectionIndicator(e) {
3017
+ let t = e.target;
3018
+ if(!t.classList.contains('art_set')) {
3019
+ t = t.closest('.art_set');
3020
+ }
3021
+ let mousePosX = (e.clientX - t.getBoundingClientRect().left);
3022
+ if(mousePosX < (t.offsetWidth/2)) {
3023
+ t.querySelector('span').classList.add('prev');
3024
+ t.querySelector('span').classList.remove('next');
3025
+ } else {
3026
+ t.querySelector('span').classList.add('next');
3027
+ t.querySelector('span').classList.remove('prev');
3028
+ }
3029
+ }
3030
+
3031
  /*
3032
  **
3033
  **
 
3050
 
3051
  function addAllListeners() {
3052
  // global
3053
+ document.addEventListener('keydown', function(e) {
3054
+ if(e.key === 'Escape' || e.keyCode === 27) {
3055
  // event.key for modern browsers, event.keyCode for older ones
3056
  enterExitEditMostUsedMode('exit');
3057
  editTagsFindArtistInEditMode();
3058
  hideInfo();
3059
  }
3060
  });
3061
+ document.addEventListener('keyup', function(e) {
3062
+ if(e.key === '/') {
3063
  showInfo();
3064
  showInformation('actions');
3065
  }
 
3117
  unhideBasedOnPermissiveSetting();
3118
  updateTags('click');
3119
  });
3120
+ } else if(checkbox.name == 'censored') {
3121
  checkbox.addEventListener('change', function(e) {
3122
+ blurUnblurCensored();
3123
  });
3124
  }
3125
  }
 
3129
  clearSelection();
3130
  storeCheckboxState(e.target);
3131
  window.setTimeout(function() {
3132
+ updateArtistsImgSrc(false);
3133
+ });
3134
  });
3135
  });
3136
  // information
 
3244
  sortAA.addEventListener('click', function(e) {
3245
  sortArtistsByAlpha();
3246
  window.setTimeout(function() {
3247
+ updateArtistsImgSrc(false);
3248
+ });
3249
  highlightSelectedOption('sortAA');
3250
  storeOptionsState();
3251
  });
 
3253
  sortAR.addEventListener('click', function(e) {
3254
  sortArtistsByRandom();
3255
  window.setTimeout(function() {
3256
+ updateArtistsImgSrc(false);
3257
+ });
3258
  highlightSelectedOption('sortAR');
3259
  storeOptionsState();
3260
  });
 
 
 
 
 
 
3261
 
3262
  // most used mode
3263
  var mostUsed = document.getElementById('edit_most_used');
 
3312
  imageItem.querySelector('.art_edit').addEventListener('click', function(e) {
3313
  editTagsClicked(this.closest('.image-item'));
3314
  });
3315
+ imageItem.querySelector('.art_set').addEventListener('click', function(e) {
3316
+ let mousePosX = (e.clientX - this.getBoundingClientRect().left);
3317
+ if(mousePosX < (this.offsetWidth/2)) {
3318
+ rotateModels(this.closest('.image-item'),-1);
3319
+ } else {
3320
+ rotateModels(this.closest('.image-item'),1);
3321
+ }
3322
+ clearSelection();
3323
+ });
3324
+ imageItem.querySelector('.art_set').addEventListener('mouseenter', function(e) {
3325
+ this.addEventListener('mousemove', rotateModelDirectionIndicator, false);
3326
+ this.addEventListener('mouseleave', function(e) {
3327
+ this.removeEventListener('mousemove', rotateModelDirectionIndicator, false);
3328
+ }, false);
3329
  });
3330
  imageItem.getElementsByTagName('h3')[0].addEventListener('click', function(e) {
3331
  copyStuffToClipboard(this,'name');
 
3334
  imageItem.getElementsByTagName('h4')[0].addEventListener('click', function(e) {
3335
  if(!this.classList.contains('edit_mode')) {
3336
  copyStuffToClipboard(this, 'tags')
 
 
3337
  }
3338
  });
3339
  });
 
3344
  gutterStartPosX = this.offsetLeft;
3345
  mouseStartPosX = e.pageX;
3346
  this.addEventListener('mousemove', movePartition, false);
3347
+ window.addEventListener('mouseup', function(e) {
3348
  gutter.removeEventListener('mousemove', movePartition, false);
3349
  }, false);
3350
  }, false);
 
3367
  promptBuilderAddArtist();
3368
  });
3369
  var prompt_selector_div = document.querySelector('#prompt_selector > div');
3370
+ prompt_selector_div.addEventListener('scroll', debouncer(function(e) {
3371
  setXPosOfSearchOutput();
3372
  }, 100));
3373
  // lazy loader
3374
  var rows = document.querySelector('#rows');
3375
+ rows.addEventListener('scroll', debouncer(function(e) {
3376
  lazyLoad();
3377
  }, 50));
3378
+ }