Mattthew commited on
Commit
fcab9ad
1 Parent(s): 16ae0cf

added slash command and tag search

Browse files

command-f no longer needed to find a tag. all help/about and "copy visible names" features moved into the slash command menu.

Files changed (3) hide show
  1. index.css +219 -76
  2. index.html +119 -113
  3. index.js +203 -89
index.css CHANGED
@@ -36,7 +36,7 @@ h4 {
36
  position: fixed;
37
  top: 0;
38
  left: 0;
39
- width: calc(60% - 20px);
40
  height: calc(100% - 80px);
41
  display: flex;
42
  flex-direction: column;
@@ -52,7 +52,7 @@ h4 {
52
  position: fixed;
53
  z-index: 1;
54
  top: 0;
55
- left: 60%;
56
  width: 50px;
57
  height: calc(100% - 40px);
58
  flex-shrink: 0;
@@ -102,42 +102,53 @@ h4 {
102
  pointer-events: none; /* Make sure the tooltip doesn't interfere with other interactions */
103
  }
104
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  #image-container {
106
  display: flex;
107
  flex-direction: row;
108
  flex-wrap: wrap;
109
  align-items: flex-start;
110
  justify-content: space-around;
111
- margin-left: calc(60% + 50px);
112
  margin-top: 20px;
113
  margin-bottom: 20px;
114
  width: 100%;
115
  }
116
 
117
- #copy-all-names {
118
- position: absolute;
119
- z-index: 2;
120
- left: calc(70% + 25px);
121
- bottom: 50px;
122
- transform: translateX(-50%);
123
- white-space: nowrap;
124
- background-color: #ffe300;
125
- opacity: 0.8;
126
- padding: 4px 8px;
127
- border-radius: 4px;
128
- box-shadow: 0 5px 10px black;
129
- font-size: 12px;
130
- font-weight: bold;
131
- color: black;
132
- cursor: pointer;
133
- transition: opacity 100ms 200ms linear;
134
- }
135
-
136
- #image-container #copy-all-names:hover {
137
- opacity: 1;
138
- transition: opacity 100ms 0ms linear;
139
- }
140
-
141
  #alert {
142
  position: fixed;
143
  z-index: 1;
@@ -243,6 +254,10 @@ footer.special #close_footer strong {
243
  transition: opacity 50ms linear;
244
  }
245
 
 
 
 
 
246
  #options_info,
247
  #options_prompts,
248
  #options_artist_sort,
@@ -250,13 +265,27 @@ footer.special #close_footer strong {
250
  margin-right: 10px;
251
  }
252
 
253
- #options_info > span:first-child,
254
  #options_prompts > span:first-child,
255
  #options_artist_sort > span:first-child,
256
  #options_tag_sort > span:first-child {
257
  margin-left: 21px;
258
  }
259
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
  #toggles label {
261
  margin: 0 20px 0 0;
262
  white-space: nowrap;
@@ -403,88 +432,202 @@ footer.special #close_footer strong {
403
  content: 'count';
404
  }
405
 
406
- .information {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
407
  display: none;
 
408
  z-index: 2;
409
  position: fixed;
410
- top: 20px;
411
- left: 20px;
412
- width: calc(40% - 40px);
413
- max-height: calc(100% - 110px);
414
- padding: 20px;
415
- overflow: auto;
 
 
 
416
  background-color: #222;
417
- border-radius: 2px;
418
- border: 1px solid black;
419
- box-shadow: 0 1px 0px #ffffff3d;
420
  }
421
 
422
- .information div {
423
- opacity: 0.8;
 
 
 
 
 
 
 
 
 
 
 
424
  }
425
 
426
- .information h2, .information h3, .information ul{
427
  margin-top: 0;
428
  margin-left: 0;
429
  }
430
 
431
- .information h3 {
432
  margin-bottom: 10px;
 
 
433
  }
434
 
435
- .information a {
436
  color: #00ffe7;
437
  font-weight: bold;
438
  text-decoration: none;
439
  }
440
 
441
-
442
- .information a:hover {
443
  color: #fff;
444
  }
445
 
446
-
447
- .information.shown {
448
- display: block;
 
449
  }
450
 
451
- #instructions {
 
 
 
 
 
 
 
 
 
 
 
 
 
452
  }
453
 
454
- #about {
 
 
 
455
 
 
 
 
456
  }
457
 
458
- #export textarea {
459
- resize: vertical;
460
  width: 100%;
461
- height: 150px;
 
 
 
 
 
462
  }
463
 
464
- #export .buttons {
 
 
 
465
  display: flex;
466
- flex-direction: row;
467
- margin-bottom: 20px;
 
 
468
  }
469
 
470
- #export .buttons div {
471
- cursor: pointer;
472
  opacity: 0.8;
473
- padding: 10px;
474
  }
475
 
476
- #export .buttons div:hover {
477
  opacity: 1;
478
  }
479
 
480
- #export #import_favorites_button, #export #delete_edits_button {
481
- opacity: 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
482
  color: #f77;
 
483
  }
484
 
485
- #export #import_favorites_button:hover, #export #delete_edits_button:hover {
 
486
  opacity: 1;
487
- color: #fff;
488
  }
489
 
490
  #filtersHidingAll {
@@ -739,23 +882,23 @@ footer.special #close_footer strong {
739
  }
740
 
741
  @keyframes enlarge {
742
- 0% {
743
- opacity: 0;
744
  transform: translateY(0px);
745
- }
746
- 100% {
747
- opacity: 1;
748
  transform: translateY(20px);
749
- }
750
  }
751
 
752
  @keyframes reduce {
753
- 0% {
754
- opacity: 0;
755
- }
756
- 100% {
757
- opacity: 1;
758
- }
759
  }
760
 
761
  .image-item .deprecated {
 
36
  position: fixed;
37
  top: 0;
38
  left: 0;
39
+ width: calc(40% - 20px);
40
  height: calc(100% - 80px);
41
  display: flex;
42
  flex-direction: column;
 
52
  position: fixed;
53
  z-index: 1;
54
  top: 0;
55
+ left: 40%;
56
  width: 50px;
57
  height: calc(100% - 40px);
58
  flex-shrink: 0;
 
102
  pointer-events: none; /* Make sure the tooltip doesn't interfere with other interactions */
103
  }
104
 
105
+ @keyframes gutter_tease {
106
+ 0% {
107
+ transform: translateX(-40px);
108
+ border-right: 1px solid #ffe300b5;
109
+ }
110
+ 10% {
111
+ transform: translateX(0px);
112
+ }
113
+ 20% {
114
+ transform: translateX(40px);
115
+ }
116
+ 30% {
117
+ transform: translateX(-20px);
118
+ }
119
+ 40% {
120
+ transform: translateX(0px);
121
+ }
122
+ 50% {
123
+ transform: translateX(20px);
124
+ }
125
+ 60% {
126
+ transform: translateX(-5px);
127
+ }
128
+ 70% {
129
+ transform: translateX(0px);
130
+ }
131
+ 80% {
132
+ transform: translateX(5px);
133
+ border-right: 1px solid #ffe300b5;
134
+ }
135
+ 90% {
136
+ transform: translateX(0px);
137
+ }
138
+ }
139
+
140
  #image-container {
141
  display: flex;
142
  flex-direction: row;
143
  flex-wrap: wrap;
144
  align-items: flex-start;
145
  justify-content: space-around;
146
+ margin-left: calc(40% + 50px);
147
  margin-top: 20px;
148
  margin-bottom: 20px;
149
  width: 100%;
150
  }
151
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  #alert {
153
  position: fixed;
154
  z-index: 1;
 
254
  transition: opacity 50ms linear;
255
  }
256
 
257
+ #options_prompts {
258
+ display: none;
259
+ }
260
+
261
  #options_info,
262
  #options_prompts,
263
  #options_artist_sort,
 
265
  margin-right: 10px;
266
  }
267
 
 
268
  #options_prompts > span:first-child,
269
  #options_artist_sort > span:first-child,
270
  #options_tag_sort > span:first-child {
271
  margin-left: 21px;
272
  }
273
 
274
+ #toggles #options_info .count {
275
+ color: #ffe300;
276
+ opacity: 0.8;
277
+ font-weight: bold;
278
+ }
279
+
280
+ #options_info i {
281
+ box-sizing: border-box;
282
+ padding: 1px 7px 1px 5px;
283
+ background-color: #777;
284
+ border: 1px solid #ddd;
285
+ border-radius: 2px;
286
+ font-size: 12px;
287
+ }
288
+
289
  #toggles label {
290
  margin: 0 20px 0 0;
291
  white-space: nowrap;
 
432
  content: 'count';
433
  }
434
 
435
+ #info_switcher {
436
+ display: flex;
437
+ flex-direction: row;
438
+ background-color: #111;
439
+ }
440
+
441
+ #info_switcher h2 {
442
+ margin: 0;
443
+ padding: 20px;
444
+ white-space: nowrap;
445
+ font-size: 16px;
446
+ cursor: pointer;
447
+ }
448
+
449
+ #info_switcher h2:hover {
450
+ background-color: #222;
451
+ }
452
+
453
+ #info_switcher h2.selected {
454
+ background-color: #222;
455
+ cursor: default;
456
+ }
457
+
458
+ #info_closer {
459
+ position: absolute;
460
+ right: 0;
461
+ font-weight: normal;
462
+ color: #555
463
+ }
464
+
465
+ #information {
466
  display: none;
467
+ flex-direction: column;
468
  z-index: 2;
469
  position: fixed;
470
+ top: 50%;
471
+ left: 50%;
472
+ transform: translateX(-50%) translateY(-50%);
473
+ width: 50%;
474
+ max-width: 600px;
475
+ height: 50%;
476
+ border: 4px solid #ffe30080;
477
+ border-radius: 20px;
478
+ box-shadow: 0 10px 20px #000;
479
  background-color: #222;
480
+ overflow: hidden;
 
 
481
  }
482
 
483
+ #information.shown {
484
+ display: flex;
485
+ }
486
+
487
+ .information_section {
488
+ display: none;
489
+ padding: 20px;
490
+ box-sizing: border-box;
491
+ overflow-y: scroll;
492
+ }
493
+
494
+ .information_section.selected {
495
+ display: block;
496
  }
497
 
498
+ .information_section h2, .information_section h3, .information_section ul{
499
  margin-top: 0;
500
  margin-left: 0;
501
  }
502
 
503
+ .information_section h3 {
504
  margin-bottom: 10px;
505
+ font-size: 16px;
506
+ color: #ffe300;
507
  }
508
 
509
+ .information_section a {
510
  color: #00ffe7;
511
  font-weight: bold;
512
  text-decoration: none;
513
  }
514
 
515
+ .information_section a:hover {
 
516
  color: #fff;
517
  }
518
 
519
+ .information_section .buttons {
520
+ display: flex;
521
+ flex-direction: row;
522
+ margin-bottom: 20px;
523
  }
524
 
525
+ .information_section .buttons div {
526
+ display: inline-block;
527
+ margin-right: 10px;
528
+ padding: 4px 8px;
529
+ opacity: 0.8;
530
+ border: 1px solid #ffe300;
531
+ border-radius: 4px;
532
+ cursor: pointer;
533
+ white-space: nowrap;
534
+ background-color: black;
535
+ color: #ffe300;
536
+ font-size: 12px;
537
+ font-weight: bold;
538
+ transition: opacity 100ms 200ms linear;
539
  }
540
 
541
+ .information_section .buttons div:hover {
542
+ opacity: 1;
543
+ transition: opacity 100ms 0ms linear;
544
+ }
545
 
546
+ #information_actions {
547
+ display: flex;
548
+ flex-direction: column;
549
  }
550
 
551
+ #info_search_input {
 
552
  width: 100%;
553
+ margin-bottom: 20px;
554
+ box-sizing: border-box;
555
+ padding: 10px;
556
+ border-radius: 4px;
557
+ border: none;
558
+ font-size: 16px;
559
  }
560
 
561
+ #info_search_output {
562
+ flex-grow: 1;
563
+ /* min-height is needed for flex-grow to to work */
564
+ min-height: 35px;
565
  display: flex;
566
+ flex-direction: column;
567
+ overflow-y: scroll;
568
+ background-color: #333;
569
+ border-radius: 4px;
570
  }
571
 
572
+ #info_search_output label {
 
573
  opacity: 0.8;
574
+ padding: 5px;
575
  }
576
 
577
+ #info_search_output label:hover {
578
  opacity: 1;
579
  }
580
 
581
+ #info_search_output label.hidden::after {
582
+ content: 'low-use is hidden';
583
+ margin-left: 10px;
584
+ position: relative;
585
+ bottom: 1px;
586
+ padding: 0px 6px;
587
+ box-sizing: border-box;
588
+ font-size: 12px;
589
+ color: #00ffe5;
590
+ background-color: black;
591
+ border-radius: 2px;
592
+ }
593
+
594
+ #info_search_output i {
595
+ display: none;
596
+ }
597
+
598
+ #info_search_output .count {
599
+ opacity: 0.5;
600
+ }
601
+
602
+ #info_search_output input {
603
+ margin-right: 10px;
604
+ }
605
+
606
+ #information_export textarea {
607
+ width: 90%;
608
+ height: 150px;
609
+ margin-bottom: 10px;
610
+ resize: vertical;
611
+ background-color: #777;
612
+ border: none;
613
+ }
614
+
615
+ #information_export #export_edits_list,
616
+ #information_export #export_artists_list {
617
+ background-color: #bbb;
618
+ cursor: not-allowed;
619
+ }
620
+
621
+ #information_export #import_favorites_button,
622
+ #information_export #delete_edits_button {
623
  color: #f77;
624
+ border: 1px solid #f77;
625
  }
626
 
627
+ #information_export #import_favorites_button:hover,
628
+ #information_export #delete_edits_button:hover {
629
  opacity: 1;
630
+ color: #f77;
631
  }
632
 
633
  #filtersHidingAll {
 
882
  }
883
 
884
  @keyframes enlarge {
885
+ 0% {
886
+ opacity: 0;
887
  transform: translateY(0px);
888
+ }
889
+ 100% {
890
+ opacity: 1;
891
  transform: translateY(20px);
892
+ }
893
  }
894
 
895
  @keyframes reduce {
896
+ 0% {
897
+ opacity: 0;
898
+ }
899
+ 100% {
900
+ opacity: 1;
901
+ }
902
  }
903
 
904
  .image-item .deprecated {
index.html CHANGED
@@ -13,127 +13,134 @@
13
  <body>
14
  <div id="layout">
15
  <div id="rows">
16
- <div id="instructions" class="information">
17
- <div>
18
- <h2>How to</h2>
19
- <h3>Clicking an artist's...</h3>
20
- <ul>
21
- <li><strong>name</strong> copies them to clipboard</li>
22
- <li><strong>tags</strong> toggles those checkmarks</li>
23
- <li><strong>star</strong> marks them as favorite</li>
24
- <li>🎨, 🧑, and 🏞️ switches the prompt/image</li>
25
- <li>✍️ enters tag-editing mode, see below</li>
26
- </ul>
27
- <h3>Permissive filter</h3>
28
- <ul>
29
- <li><strong>checked:</strong> artists matching <strong>any</strong> checked tags</li>
30
- <li><strong>unchecked:</strong> artists matching <strong>all</strong> checked tags</li>
31
- <li>use unchecked to filter your favorites</li>
32
- </ul>
33
- <h3>Hide low-use tags</h3>
34
- <ul>
35
- <li><strong>checked:</strong> hides tags that match less than 4 artists, ~50% of all tags</li>
36
- <li>note that all hidden tags are unchecked</li>
37
- </ul>
38
- <h3>Hide unknown to SDXL</h3>
39
- <ul>
40
- <li>I've hand verified that SDXL doesn't know these artists' styles</li>
41
- <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>
42
- <li>They're included in the database for the record of whar SDXL doesn't know, but the images may be removed.</li>
43
- </ul>
44
- <h3>When using Stable Diffusion</h3>
45
- <ul>
46
- <li>Reproduce these styles with the prompt with "by {Artist full name}, ...."</li>
47
- <li>Adding the style tags to the prompt can also help</li>
48
- <li>You can combine the styles of two are more artists</li>
49
- </ul>
50
- <h3>✍️ Tag-editing is only for offline use!</h3>
51
- <ul>
52
- <li>If you are viewing this from Hugging Face, your tag edits won't be applied. They'll be saved and applied if you've downloaded the repository and are viewing your local file. In both cases, your edits will be available for export 📥 as text. If you want to suggestions for tag improvements for everyone's benefit, then 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>
53
- </ul>
54
  </div>
55
- </div>
56
- <div id="about" class="information">
57
- <div>
58
- <h2>About</h2>
59
- <h3>Incomplete beta version!</h3>
60
- <p>
61
- I'll add thousands more artists to the database soon. I want to work out any major issues first. Please <a href="https://huggingface.co/spaces/mattthew/SDXL-artists-browser/discussions" target="_blank">give feedback on Huggingface</a>.
62
- </p>
63
- <h3>How to support this project</h3>
64
- <ul>
65
- <li>Please tell a friends or share on your socials</li>
66
- <li>Suggest artists I should add or remove</li>
67
- <li>Suggest features and report bugs</li>
68
- <li><a href="https://huggingface.co/spaces/mattthew/SDXL-artists-browser/discussions" target="_blank">Leave all feedback on Huggingface</a></li>
69
- <li>I don't need money. Thanks always feels nice!</li>
70
- </ul>
71
- <h3>Image parameters</h3>
72
- <ul>
73
- <li>
74
- All: Steps: 20, Sampler: DPM++ 2M Karras, CFG scale: 10, Seed: 42 or 43, Size: 1024x1024, Model hash: 31e35c80fc, Model: sd_xl_base_1.0, Version: v1.5.1 (no refiner pass)
75
- </li>
76
- <li>
77
- 🎨 Prompt: by {Artist full name}, artwork image, Negative prompt: frame, border, text, signature
78
- </li>
79
- <li>
80
- 🧑 Prompt: by {Artist full name}, image of a gently smiling face, portrait of a person, head and torso, sitting in their room, Negative prompt: self-portrait, outside, frame, border, text, signature
81
- </li>
82
- <li>
83
- 🏞️ Prompt: by {Artist full name}, image of a landscape, outdoor natural scenery, water, bridge, Negative prompt: people, person, frame, border, text, signature
84
- </li>
85
- </ul>
86
- <h3>Disclaimers</h3>
87
- <ul>
88
- <li>This tools is just for fun. This information NOT be correct! The tags are from a mix of sources and manual input. Many tags are AI generated. I make corrections when I happen to spot them or when submitted.</li>
89
- <li>Remember, SDXL is only a crude imitation of these artists. Check out these artists' actual artwork for more inspiration!</li>
90
- <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 artists I should add.</li>
91
- <li>My code doesn't use cookies and sends nothing to any server. But it's hosted on Huggingface, and I can't control if they cookie you</li>
92
- <li>Open source. Creatives Commons license. Download for free.</li>
93
- <li>I don't get nor do I want compensation for this</li>
94
- <li>I'm not affiliated with Stability AI</li>
95
- <li>Use at your own risk 🧟</li>
96
- </ul>
97
- <h3>Why do many images show a car?</h3>
98
- <ul>
99
- <li>
100
- It's an artifact of the way SDXL was trained. It appears consistently, but not always, for any prompt doesn't include a specific subject. Surprisingly, the car appears for many artists, for many different seeds, and for many different prompts and negative prompts. For example, I use the non-specific 🎨 prompt, "artwork image". I picked that intentionally to reveal the subject matter biases SDXL has for each artist. This artifact of SDXL probably reveals a bias of the model towards generating car images.
101
- </li>
102
- </ul>
103
- <h3>Missing images</h3>
104
- <p>
105
- If artists are listed in the database file, but their image files are missing, the files are listed below.
106
- </p>
107
- <ul id="missing_images_report"></ul>
108
- </div>
109
- </div>
110
- <div id="export" class="information">
111
- <div>
112
- <h3>Export/Import favorited artists</h2>
113
- <textarea id="export_favorites_list" placeholder="You haven't favorited any artists yet."></textarea>
114
  <div class="buttons">
115
- <div id="export_favorites_button">copy to clipboard</div>
116
- <div id="import_favorites_button">import</div>
117
  </div>
118
- <h3>Export tag-edits to send to author</h2>
119
- <textarea id="export_edits_list" placeholder="You haven't edited any tags yet."></textarea>
120
- <div class="buttons">
121
- <div id="export_edits_button">copy to clipboard</div>
122
- <div id="delete_edits_button">restore official database</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  </div>
124
- <h3>Export database</h2>
125
- <textarea id="export_artists_list"></textarea>
126
- <div class="buttons">
127
- <div id="export_artists_button">copy to clipboard</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  </div>
129
  </div>
130
  </div>
131
  <div id="toggles">
132
  <div id="options_info">
133
- <span class="count">documents:</span>
134
- <span class="link" id="infoI">⁉️&nbsp;</span>
135
- <span class="link" id="infoA">📓&nbsp;</span>
136
- <span class="link" id="infoX">📤&nbsp;</span>
137
  </div>
138
  <div id="options_prompts">
139
  <span class="count">show me:</span>
@@ -187,7 +194,6 @@
187
  check-mark any tag or ‟permissive”<br>
188
  👀
189
  </div>
190
- <div id="copy-all-names">copy all visible names</div>
191
  <!-- JS will insert images here -->
192
  <!--
193
  <div class="image-item tag1 tag2">
 
13
  <body>
14
  <div id="layout">
15
  <div id="rows">
16
+ <div id="information">
17
+ <div id="info_switcher">
18
+ <h2 id="info_actions" class="selected">🔍&nbsp;&nbsp;&nbsp;actions</h2>
19
+ <h2 id="info_help">⁉️&nbsp;&nbsp;&nbsp;how to</h2>
20
+ <h2 id="info_about">📓&nbsp;&nbsp;&nbsp;about</h2>
21
+ <h2 id="info_export">📤&nbsp;&nbsp;&nbsp;export</h2>
22
+ <h2 id="info_closer">ESC</h2>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  </div>
24
+ <div id="information_actions" class="information_section selected">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  <div class="buttons">
26
+ <div id="copy-all-names">copy matching artist names</div>
 
27
  </div>
28
+ <input type="text" id="info_search_input" name="info_search_input" value="" data-match="" placeholder="search for tags" autocomplete="off">
29
+ <div id="info_search_output"></div>
30
+ </div>
31
+ <div id="information_help" class="information_section">
32
+ <div>
33
+ <h3>Clicking an artist's...</h3>
34
+ <ul>
35
+ <li><strong>name</strong> copies them to clipboard</li>
36
+ <li><strong>tags</strong> toggles those checkmarks</li>
37
+ <li><strong>star</strong> marks them as favorite</li>
38
+ <li>🎨, 🧑, and 🏞️ switches the prompt/image</li>
39
+ <li>✍️ enters tag-editing mode, see below</li>
40
+ </ul>
41
+ <h3>Permissive filter</h3>
42
+ <ul>
43
+ <li><strong>checked:</strong> artists matching <strong>any</strong> checked tags</li>
44
+ <li><strong>unchecked:</strong> artists matching <strong>all</strong> checked tags</li>
45
+ <li>use unchecked to filter your favorites</li>
46
+ </ul>
47
+ <h3>Hide low-use tags</h3>
48
+ <ul>
49
+ <li><strong>checked:</strong> hides tags that match less than 4 artists, ~50% of all tags</li>
50
+ <li>note that all hidden tags are unchecked</li>
51
+ </ul>
52
+ <h3>Hide unknown to SDXL</h3>
53
+ <ul>
54
+ <li>I've hand verified that SDXL doesn't know these artists' styles</li>
55
+ <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>
56
+ <li>They're included in the database for the record of whar SDXL doesn't know, but the images may be removed.</li>
57
+ </ul>
58
+ <h3>When using Stable Diffusion</h3>
59
+ <ul>
60
+ <li>Reproduce these styles with the prompt with "by {Artist full name}, ...."</li>
61
+ <li>Adding the style tags to the prompt can also help</li>
62
+ <li>You can combine the styles of two are more artists</li>
63
+ </ul>
64
+ <h3>✍️ Tag-editing is only for offline use!</h3>
65
+ <ul>
66
+ <li>If you are viewing this from Hugging Face, your tag edits won't be applied. They'll be saved and applied if you've downloaded the repository and are viewing your local file. In both cases, your edits will be available for export 📥 as text. If you want to suggestions for tag improvements for everyone's benefit, then 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>
67
+ </ul>
68
  </div>
69
+ </div>
70
+ <div id="information_about" class="information_section">
71
+ <div>
72
+ <h3>How to support this project</h3>
73
+ <ul>
74
+ <li>Please tell a friends or share on your socials</li>
75
+ <li>Suggest artists I should add or remove</li>
76
+ <li>Suggest features and report bugs</li>
77
+ <li><a href="https://huggingface.co/spaces/mattthew/SDXL-artists-browser/discussions" target="_blank">Leave all feedback on Huggingface</a></li>
78
+ <li>I don't need money. Thanks always feels nice!</li>
79
+ </ul>
80
+ <h3>Image parameters</h3>
81
+ <ul>
82
+ <li>
83
+ All: Steps: 20, Sampler: DPM++ 2M Karras, CFG scale: 10, Seed: 42 or 43, Size: 1024x1024, Model hash: 31e35c80fc, Model: sd_xl_base_1.0, Version: v1.5.1 (no refiner pass)
84
+ </li>
85
+ <li>
86
+ 🎨 Prompt: by {Artist full name}, artwork image, Negative prompt: frame, border, text, signature
87
+ </li>
88
+ <li>
89
+ 🧑 Prompt: by {Artist full name}, image of a gently smiling face, portrait of a person, head and torso, sitting in their room, Negative prompt: self-portrait, outside, frame, border, text, signature
90
+ </li>
91
+ <li>
92
+ 🏞️ Prompt: by {Artist full name}, image of a landscape, outdoor natural scenery, water, bridge, Negative prompt: people, person, frame, border, text, signature
93
+ </li>
94
+ </ul>
95
+ <h3>Disclaimers</h3>
96
+ <ul>
97
+ <li>This tools is just for fun. This information NOT be correct! The tags are from a mix of sources and manual input. Many tags are AI generated. I make corrections when I happen to spot them or when submitted.</li>
98
+ <li>Remember, SDXL is only a crude imitation of these artists. Check out these artists' actual artwork for more inspiration!</li>
99
+ <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 artists I should add.</li>
100
+ <li>My code doesn't use cookies and sends nothing to any server. But it's hosted on Huggingface, and I can't control if they cookie you</li>
101
+ <li>Open source. Creatives Commons license. Download for free.</li>
102
+ <li>I don't get nor do I want compensation for this</li>
103
+ <li>I'm not affiliated with Stability AI</li>
104
+ <li>Use at your own risk 🧟</li>
105
+ </ul>
106
+ <h3>Why do many images show a car?</h3>
107
+ <ul>
108
+ <li>
109
+ It's an artifact of the way SDXL was trained. It appears consistently, but not always, for any prompt doesn't include a specific subject. Surprisingly, the car appears for many artists, for many different seeds, and for many different prompts and negative prompts. For example, I use the non-specific 🎨 prompt, "artwork image". I picked that intentionally to reveal the subject matter biases SDXL has for each artist. This artifact of SDXL probably reveals a bias of the model towards generating car images.
110
+ </li>
111
+ </ul>
112
+ <h3>Missing images</h3>
113
+ <p>
114
+ If artists are listed in the database file, but their image files are missing, the files are listed below.
115
+ </p>
116
+ <ul id="missing_images_report"></ul>
117
+ </div>
118
+ </div>
119
+ <div id="information_export" class="information_section">
120
+ <div>
121
+ <h3>Export/Import favorited artists</h3>
122
+ <textarea id="export_favorites_list" value="" placeholder="You haven't favorited any artists yet." autocomplete="off"></textarea>
123
+ <div class="buttons">
124
+ <div id="export_favorites_button">copy to clipboard</div>
125
+ <div id="import_favorites_button">import</div>
126
+ </div>
127
+ <h3>Export tag-edits to send to author</h3>
128
+ <textarea id="export_edits_list" value="" placeholder="You haven't edited any tags yet." autocomplete="off" disabled="true"></textarea>
129
+ <div class="buttons">
130
+ <div id="export_edits_button">copy to clipboard</div>
131
+ <div id="delete_edits_button">restore official database</div>
132
+ </div>
133
+ <h3>Export database</h3>
134
+ <textarea id="export_artists_list" value="" placeholder="If this is visible, there's a bug" autocomplete="off" disabled="true"></textarea>
135
+ <div class="buttons">
136
+ <div id="export_artists_button">copy to clipboard</div>
137
+ </div>
138
  </div>
139
  </div>
140
  </div>
141
  <div id="toggles">
142
  <div id="options_info">
143
+ <span class="count">press <i>/</i> key for actions</span>
 
 
 
144
  </div>
145
  <div id="options_prompts">
146
  <span class="count">show me:</span>
 
194
  check-mark any tag or ‟permissive”<br>
195
  👀
196
  </div>
 
197
  <!-- JS will insert images here -->
198
  <!--
199
  <div class="image-item tag1 tag2">
index.js CHANGED
@@ -8,6 +8,7 @@ var artTypes = ['🎨','🧑','🏞️'];
8
  var imgTypeShown = 0;
9
  var log = '';
10
  var editMostUsedMode = false;
 
11
  var windowWidth = 0;
12
  var gutterStartPosX, mouseStartPosX, gutterEndPercentX
13
  var style, tempStyle, stylesheet, tempStylesheet, imgHoverRule, teaseRules;
@@ -496,7 +497,8 @@ function storeCheckboxStateAll(isChecked) {
496
  async function loadOptionsState() {
497
  await loadItemBasedOnAccessType('optionsChecked').then(state => {
498
  if(state['prompt']) {
499
- document.getElementById('options_prompts').querySelectorAll('.selected')[0].classList.remove('selected');
 
500
  document.getElementById(state['prompt']).classList.add('selected');
501
  if(state['prompt'] == 'promptA') {
502
  imgTypeShown = 0;
@@ -533,7 +535,8 @@ function highlightSelectedOption(selected) {
533
  imgTypeShown++;
534
  if(imgTypeShown > 2) { imgTypeShown = 0; }
535
  }
536
- var links = document.getElementById('options_prompts').querySelectorAll('.link');
 
537
  links.forEach(function(link) {
538
  link.classList.remove('selected');
539
  });
@@ -773,10 +776,8 @@ function unhideBasedOnPermissiveSetting() {
773
  var unHidden = document.querySelectorAll('.image-item').length - document.querySelectorAll('.image-item.hidden').length;
774
  if(unHidden == 0) {
775
  document.getElementById('filtersHidingAll').classList.add('shown');
776
- document.getElementById('copy-all-names').style.display = 'none'
777
  } else {
778
  document.getElementById('filtersHidingAll').classList.remove('shown');
779
- document.getElementById('copy-all-names').style.display = ''
780
  }
781
  }
782
 
@@ -889,26 +890,129 @@ function checkOrUncheckAll(isChecked) {
889
  }
890
  }
891
 
892
- function showInstructions() {
893
- document.getElementById('instructions').classList.add('shown');
894
- hideToggles();
895
  }
896
 
897
- function showAbout() {
898
- document.getElementById('about').classList.add('shown');
899
- hideToggles();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
900
  }
901
 
902
  function showExport() {
903
- hideToggles();
904
- document.getElementById('export').classList.add('shown');
905
  // favorites
906
  var textareaF = document.getElementById('export_favorites_list');
907
  var favoritedArtists = false;
908
  loadItemBasedOnAccessType('favoritedArtists').then(state => {
909
  var value = '';
910
  if(state) {
911
- value += '\r\n\r\nTo import these favorites later, click "copy to clipboard" and save to any file. Then paste the text from that file into this text box, and click "import". The imported text must contain the JSON string below (the curly brackets and what\'s between them).\r\n\r\n' + JSON.stringify(state);
912
  textareaF.value = value;
913
  } else {
914
  value += 'You haven\'t favorited any artists yet.\r\n\r\n';
@@ -1021,14 +1125,6 @@ function importFavorites() {
1021
  }
1022
  }
1023
 
1024
- function hideInformation() {
1025
- var information = document.querySelectorAll('.information');
1026
- information.forEach(function(element) {
1027
- element.classList.remove('shown');
1028
- });
1029
- showToggles();
1030
- }
1031
-
1032
  function sortTags() {
1033
  if(document.getElementById('sortTC').classList.contains('selected')) {
1034
  sortTagsByCount();
@@ -1450,13 +1546,17 @@ function copyStuffToClipboard(item,stuff) {
1450
  str += item.querySelectorAll('h3 span')[1].textContent + '\n';
1451
  count++;
1452
  }
1453
- navigator.clipboard.writeText(str)
1454
- .then(() => {
1455
- doAlert('Copied ' + count.toLocaleString() + ' names to clipboard!',1);
1456
- })
1457
- .catch(() => {
1458
- doAlert('😭😭 Can\'t access clipboard',1);
1459
- });
 
 
 
 
1460
  }
1461
  }
1462
 
@@ -1615,7 +1715,6 @@ function movePartition(e) {
1615
  document.getElementById('toggles').style.width = 'calc(' + gutterEndPercentX + '% - 20px)';
1616
  document.getElementById('gutter').style.left = gutterEndPercentX + '%';
1617
  document.getElementById('image-container').style.marginLeft = 'calc(' + gutterEndPercentX + '% + 50px)';
1618
- document.getElementById('copy-all-names').style.left = 'calc(' + (gutterEndPercentX + ((100-gutterEndPercentX)/2)) + '% + 25px)';
1619
  imgHoverRule.style.width = gutterEndPercentX + '%';
1620
  // prevent text from being selected during drag
1621
  if (window.getSelection) {
@@ -1637,22 +1736,19 @@ function teasePartition() {
1637
  tempStyle.id = 'teaseDragStyle';
1638
  document.head.appendChild(tempStyle);
1639
  tempStylesheet = tempStyle.sheet;
1640
- // add temporary transitions
1641
- tempStylesheet.insertRule('#toggles { transition: width 200ms ease-out; }', 0);
1642
- tempStylesheet.insertRule('#gutter { transition: left 200ms ease-out; }', 0);
1643
- tempStylesheet.insertRule('#image-container { transition: margin-left 200ms ease-out, opacity 200ms 200ms linear; }', 0);
1644
- document.getElementById('image-container').style.opacity = 0;
1645
- // set position
1646
  window.setTimeout(function() {
1647
- let gutterEndPercentX = 40;
1648
- document.getElementById('toggles').style.width = 'calc(' + gutterEndPercentX + '% - 20px)';
1649
- document.getElementById('gutter').style.left = gutterEndPercentX + '%';
1650
- document.getElementById('image-container').style.marginLeft = 'calc(' + gutterEndPercentX + '% + 50px)';
1651
- document.getElementById('image-container').style.opacity = '';
1652
- },600);
 
 
1653
  window.setTimeout(function() {
1654
  document.getElementById('teaseDragStyle').remove();
1655
- },1000);
1656
  }
1657
 
1658
  function editTagsClicked(clickedImageItem) {
@@ -1927,6 +2023,28 @@ function deleteAllEdits() {
1927
  }
1928
 
1929
  function addAllListeners() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1930
  // checkboxes
1931
  var checkboxes = document.querySelectorAll('input[type="checkbox"]');
1932
  checkboxes.forEach(function(checkbox) {
@@ -1978,39 +2096,35 @@ function addAllListeners() {
1978
  }
1979
  }
1980
  });
1981
- // options
1982
- var infoI = document.getElementById('infoI');
1983
- infoI.addEventListener('click', function(e) {
1984
- showInstructions();
1985
  });
1986
- var infoA = document.getElementById('infoA');
1987
- infoA.addEventListener('click', function(e) {
1988
- showAbout();
1989
  });
1990
- var infoE = document.getElementById('infoX');
1991
- infoX.addEventListener('click', function(e) {
1992
- showExport();
1993
  });
1994
- // prompts
1995
- var promptA = document.getElementById('promptA');
1996
- promptA.addEventListener('click', function(e) {
1997
- highlightSelectedOption('promptA');
1998
- rotatePromptsImages();
1999
- storeOptionsState();
2000
  });
2001
- var promptP = document.getElementById('promptP');
2002
- promptP.addEventListener('click', function(e) {
2003
- highlightSelectedOption('promptP');
2004
- rotatePromptsImages();
2005
- storeOptionsState();
2006
  });
2007
- var promptL = document.getElementById('promptL');
2008
- promptL.addEventListener('click', function(e) {
2009
- highlightSelectedOption('promptL');
2010
- rotatePromptsImages();
2011
- storeOptionsState();
 
 
2012
  });
2013
- // information
2014
  var export_favorites = document.getElementById('export_favorites_button');
2015
  export_favorites.addEventListener('click', function(e) {
2016
  exportTextarea('favorites');
@@ -2031,14 +2145,27 @@ function addAllListeners() {
2031
  export_artists.addEventListener('click', function(e) {
2032
  exportTextarea('artists');
2033
  });
2034
- var information = document.querySelectorAll('.information');
2035
- information.forEach(function(element) {
2036
- element.addEventListener('mouseleave', function(e) {
2037
- if (!element.contains(e.relatedTarget)) {
2038
- hideInformation();
2039
- }
2040
- });
2041
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
2042
  // sorting
2043
  var sortTA = document.getElementById('sortTA');
2044
  sortTA.addEventListener('click', function(e) {
@@ -2069,14 +2196,6 @@ function addAllListeners() {
2069
  mostUsed.addEventListener('click', function(e) {
2070
  enterExitEditMostUsedMode();
2071
  });
2072
- document.addEventListener('keydown', function(event) {
2073
- if (event.key === 'Escape' || event.keyCode === 27) {
2074
- // event.key for modern browsers, event.keyCode for older ones
2075
- enterExitEditMostUsedMode('exit');
2076
- editTagsFindArtistInEditMode();
2077
- hideInformation();
2078
- }
2079
- });
2080
  var labels = document.querySelectorAll('label');
2081
  Array.from(labels).forEach(function(label) {
2082
  label.addEventListener('click', function(e) {
@@ -2141,11 +2260,6 @@ function addAllListeners() {
2141
  gutter.removeEventListener('mousemove', movePartition, false);
2142
  }, false);
2143
  }, false);
2144
- // copy-all
2145
- var copyAllNames = document.getElementById('copy-all-names');
2146
- copyAllNames.addEventListener('click', function(e) {
2147
- copyStuffToClipboard(this, 'copyAllNames')
2148
- });
2149
  // footer
2150
  var closeFooter = document.getElementById('close_footer');
2151
  closeFooter.addEventListener('click', function(e) {
 
8
  var imgTypeShown = 0;
9
  var log = '';
10
  var editMostUsedMode = false;
11
+ var informationMode = false;
12
  var windowWidth = 0;
13
  var gutterStartPosX, mouseStartPosX, gutterEndPercentX
14
  var style, tempStyle, stylesheet, tempStylesheet, imgHoverRule, teaseRules;
 
497
  async function loadOptionsState() {
498
  await loadItemBasedOnAccessType('optionsChecked').then(state => {
499
  if(state['prompt']) {
500
+ let optionsPrompts = document.getElementById('options_prompts');
501
+ optionsPrompts.querySelectorAll('.selected')[0].classList.remove('selected');
502
  document.getElementById(state['prompt']).classList.add('selected');
503
  if(state['prompt'] == 'promptA') {
504
  imgTypeShown = 0;
 
535
  imgTypeShown++;
536
  if(imgTypeShown > 2) { imgTypeShown = 0; }
537
  }
538
+ let optionsPrompts = document.getElementById('options_prompts');
539
+ var links = optionsPrompts.querySelectorAll('.link');
540
  links.forEach(function(link) {
541
  link.classList.remove('selected');
542
  });
 
776
  var unHidden = document.querySelectorAll('.image-item').length - document.querySelectorAll('.image-item.hidden').length;
777
  if(unHidden == 0) {
778
  document.getElementById('filtersHidingAll').classList.add('shown');
 
779
  } else {
780
  document.getElementById('filtersHidingAll').classList.remove('shown');
 
781
  }
782
  }
783
 
 
890
  }
891
  }
892
 
893
+ function showInfo() {
894
+ document.getElementById('information').classList.add('shown');
895
+ informationMode = true;
896
  }
897
 
898
+ function hideInfo() {
899
+ document.getElementById('info_search_input').value = '';
900
+ document.getElementById('information').classList.remove('shown');
901
+ informationMode = false;
902
+ }
903
+
904
+ function showInformation(tab) {
905
+ let information = document.querySelectorAll('.information_section');
906
+ information.forEach(function(element) {
907
+ element.classList.remove('selected');
908
+ });
909
+ document.getElementById('information_' + tab).classList.add('selected');
910
+ let info = document.querySelectorAll('#info_switcher h2');
911
+ info.forEach(function(element) {
912
+ element.classList.remove('selected');
913
+ });
914
+ document.getElementById('info_' + tab).classList.add('selected');
915
+ if (tab == 'actions') {
916
+ document.getElementById('info_search_input').focus();
917
+ } else if(tab == 'export') {
918
+ showExport();
919
+ }
920
+ }
921
+
922
+ function searchForTagsInfo() {
923
+ let input = document.getElementById('info_search_input');
924
+ if(input.dataset.match != '') {
925
+ event.preventDefault();
926
+ if(event.key === 'Backspace' || event.keyCode === 8) {
927
+ input.value = '';
928
+ input.dataset.match = '';
929
+ } else {
930
+ input.value = input.dataset.match;
931
+ }
932
+ return;
933
+ }
934
+ let output = document.getElementById('info_search_output');
935
+ output.innerHTML = '';
936
+ let matches = 0;
937
+ let match = '';
938
+ let range = 'start'
939
+ let tags = document.querySelectorAll('#toggles label:not(.top_control):not(.category)');
940
+ tags.forEach(function(tag) {
941
+ let tagName = tag.querySelector('input').name;
942
+ if(tagName.toLowerCase().indexOf(input.value.toLowerCase()) > -1) {
943
+ range = 'continue';
944
+ let label = tag.cloneNode(true);
945
+ label.addEventListener('change', function(e) {
946
+ toggleMatchingTag(this);
947
+ });
948
+ output.appendChild(label);
949
+ match = tagName;
950
+ matches++;
951
+ } else {
952
+ if(range != 'start') {
953
+ range = 'stop';
954
+ }
955
+ }
956
+ if(range == 'stop') {
957
+ return;
958
+ }
959
+ });
960
+ if(matches == 1) {
961
+ input.value = match;
962
+ event.preventDefault();
963
+ input.dataset.match = match;
964
+ } else {
965
+ sortInfoSearchTags(output);
966
+ }
967
+ }
968
+
969
+ function sortInfoSearchTags(output) {
970
+ let labels = Array.from(output.querySelectorAll('label'));
971
+ let sortByCount = document.getElementById('sortTC').classList.contains('selected');
972
+ labels.sort(function(a, b) {
973
+ if(sortByCount) {
974
+ var numA = parseInt(a.querySelector('.count').textContent.replace(/,/g, '').trim().substring(2),10);
975
+ var numB = parseInt(b.querySelector('.count').textContent.replace(/,/g, '').trim().substring(2),10);
976
+ return numB - numA;
977
+ } else {
978
+ var aValue = a.querySelector('input[type="checkbox"]').name;
979
+ var bValue = b.querySelector('input[type="checkbox"]').name;
980
+ return aValue.localeCompare(bValue);
981
+ }
982
+ });
983
+ labels.forEach(function(label) {
984
+ output.appendChild(label);
985
+ });
986
+ }
987
+
988
+ function toggleMatchingTag(searchLabel) {
989
+ let toggleLabels = document.getElementById('toggles').querySelectorAll('label');
990
+ let searchInput = searchLabel.querySelector('input');
991
+ let toggleMatch;
992
+ toggleLabels.forEach(function(label) {
993
+ let toggleInput = label.querySelector('input');
994
+ if(toggleInput.value == searchInput.value) {
995
+ toggleMatch = label;
996
+ return;
997
+ }
998
+ });
999
+ toggleMatch.querySelector('input').checked = searchInput.checked;
1000
+ hideAllArtists();
1001
+ unhideBasedOnPermissiveSetting();
1002
+ storeCheckboxState(toggleMatch);
1003
+ updateArtistsCountPerTag('click');
1004
+ let input = document.getElementById('info_search_input');
1005
+ input.focus();
1006
  }
1007
 
1008
  function showExport() {
 
 
1009
  // favorites
1010
  var textareaF = document.getElementById('export_favorites_list');
1011
  var favoritedArtists = false;
1012
  loadItemBasedOnAccessType('favoritedArtists').then(state => {
1013
  var value = '';
1014
  if(state) {
1015
+ value += 'To import these favorites later, click "copy to clipboard" and save to any file. Then paste the text from that file into this text box, and click "import". The imported text must contain the JSON string below (the curly brackets and what\'s between them).\r\n\r\n' + JSON.stringify(state);
1016
  textareaF.value = value;
1017
  } else {
1018
  value += 'You haven\'t favorited any artists yet.\r\n\r\n';
 
1125
  }
1126
  }
1127
 
 
 
 
 
 
 
 
 
1128
  function sortTags() {
1129
  if(document.getElementById('sortTC').classList.contains('selected')) {
1130
  sortTagsByCount();
 
1546
  str += item.querySelectorAll('h3 span')[1].textContent + '\n';
1547
  count++;
1548
  }
1549
+ if(count > 0) {
1550
+ navigator.clipboard.writeText(str)
1551
+ .then(() => {
1552
+ doAlert('Copied ' + count.toLocaleString() + ' names to clipboard!',1);
1553
+ })
1554
+ .catch(() => {
1555
+ doAlert('😭😭 Can\'t access clipboard',1);
1556
+ });
1557
+ } else {
1558
+ doAlert('No artists are visible!',1);
1559
+ }
1560
  }
1561
  }
1562
 
 
1715
  document.getElementById('toggles').style.width = 'calc(' + gutterEndPercentX + '% - 20px)';
1716
  document.getElementById('gutter').style.left = gutterEndPercentX + '%';
1717
  document.getElementById('image-container').style.marginLeft = 'calc(' + gutterEndPercentX + '% + 50px)';
 
1718
  imgHoverRule.style.width = gutterEndPercentX + '%';
1719
  // prevent text from being selected during drag
1720
  if (window.getSelection) {
 
1736
  tempStyle.id = 'teaseDragStyle';
1737
  document.head.appendChild(tempStyle);
1738
  tempStylesheet = tempStyle.sheet;
1739
+ // apply temporary rules
 
 
 
 
 
1740
  window.setTimeout(function() {
1741
+ tempStylesheet.insertRule('#gutter div { '
1742
+ + 'animation-name: gutter_tease;'
1743
+ + 'animation-duration: 800ms;'
1744
+ + 'animation-timing-function: ease-out;'
1745
+ + 'animation-iteration-count: 1;'
1746
+ + 'animation-direction: forward;'
1747
+ + '}', 0);
1748
+ },1000);
1749
  window.setTimeout(function() {
1750
  document.getElementById('teaseDragStyle').remove();
1751
+ },2000);
1752
  }
1753
 
1754
  function editTagsClicked(clickedImageItem) {
 
2023
  }
2024
 
2025
  function addAllListeners() {
2026
+ // global
2027
+ document.addEventListener('keydown', function(event) {
2028
+ if(event.key === 'Escape' || event.keyCode === 27) {
2029
+ // event.key for modern browsers, event.keyCode for older ones
2030
+ enterExitEditMostUsedMode('exit');
2031
+ editTagsFindArtistInEditMode();
2032
+ hideInfo();
2033
+ }
2034
+ });
2035
+ document.addEventListener('keyup', function(event) {
2036
+ if(event.key === '/') {
2037
+ showInfo();
2038
+ showInformation('actions');
2039
+ }
2040
+ });
2041
+ document.querySelector('body').addEventListener('click', function(e) {
2042
+ if(informationMode) {
2043
+ if(!e.target.closest('#information')) {
2044
+ hideInfo();
2045
+ }
2046
+ }
2047
+ });
2048
  // checkboxes
2049
  var checkboxes = document.querySelectorAll('input[type="checkbox"]');
2050
  checkboxes.forEach(function(checkbox) {
 
2096
  }
2097
  }
2098
  });
2099
+ // information
2100
+ var info_actions = document.getElementById('info_actions');
2101
+ info_actions.addEventListener('click', function(e) {
2102
+ showInformation('actions');
2103
  });
2104
+ var info_help = document.getElementById('info_help');
2105
+ info_help.addEventListener('click', function(e) {
2106
+ showInformation('help');
2107
  });
2108
+ var info_about = document.getElementById('info_about');
2109
+ info_about.addEventListener('click', function(e) {
2110
+ showInformation('about');
2111
  });
2112
+ var info_export = document.getElementById('info_export');
2113
+ info_export.addEventListener('click', function(e) {
2114
+ showInformation('export');
 
 
 
2115
  });
2116
+ var info_closer = document.getElementById('info_closer');
2117
+ info_closer.addEventListener('click', function(e) {
2118
+ hideInfo();
 
 
2119
  });
2120
+ var info_search = document.getElementById('info_search_input')
2121
+ info_search.addEventListener('keyup', function(e) {
2122
+ searchForTagsInfo(e);
2123
+ });
2124
+ var copyAllNames = document.getElementById('copy-all-names');
2125
+ copyAllNames.addEventListener('click', function(e) {
2126
+ copyStuffToClipboard(this, 'copyAllNames')
2127
  });
 
2128
  var export_favorites = document.getElementById('export_favorites_button');
2129
  export_favorites.addEventListener('click', function(e) {
2130
  exportTextarea('favorites');
 
2145
  export_artists.addEventListener('click', function(e) {
2146
  exportTextarea('artists');
2147
  });
2148
+ // prompts
2149
+ /*
2150
+ var promptA = document.getElementById('promptA');
2151
+ promptA.addEventListener('click', function(e) {
2152
+ highlightSelectedOption('promptA');
2153
+ rotatePromptsImages();
2154
+ storeOptionsState();
2155
  });
2156
+ var promptP = document.getElementById('promptP');
2157
+ promptP.addEventListener('click', function(e) {
2158
+ highlightSelectedOption('promptP');
2159
+ rotatePromptsImages();
2160
+ storeOptionsState();
2161
+ });
2162
+ var promptL = document.getElementById('promptL');
2163
+ promptL.addEventListener('click', function(e) {
2164
+ highlightSelectedOption('promptL');
2165
+ rotatePromptsImages();
2166
+ storeOptionsState();
2167
+ });
2168
+ */
2169
  // sorting
2170
  var sortTA = document.getElementById('sortTA');
2171
  sortTA.addEventListener('click', function(e) {
 
2196
  mostUsed.addEventListener('click', function(e) {
2197
  enterExitEditMostUsedMode();
2198
  });
 
 
 
 
 
 
 
 
2199
  var labels = document.querySelectorAll('label');
2200
  Array.from(labels).forEach(function(label) {
2201
  label.addEventListener('click', function(e) {
 
2260
  gutter.removeEventListener('mousemove', movePartition, false);
2261
  }, false);
2262
  }, false);
 
 
 
 
 
2263
  // footer
2264
  var closeFooter = document.getElementById('close_footer');
2265
  closeFooter.addEventListener('click', function(e) {