Spaces:
Running
Running
Mattthew
commited on
Commit
•
a4898fa
1
Parent(s):
0c16b46
fixing bug for chrome security settings
Browse filesChrome is stupid. No way to save beyond the session, but at leas the app works now
index.js
CHANGED
@@ -15,11 +15,13 @@ var theTime = new Date;
|
|
15 |
var startUpTime;
|
16 |
var tagsConcatenated = new Set();
|
17 |
var editedArtists = new Set();
|
|
|
18 |
//
|
19 |
//
|
20 |
//
|
21 |
// functions
|
22 |
function startUp() {
|
|
|
23 |
updateTagsConcatenated();
|
24 |
updateFooter();
|
25 |
loadEditedArtists();
|
@@ -41,6 +43,36 @@ function startUp() {
|
|
41 |
showHideLowCountTags();
|
42 |
makeStyleRuleForDrag();
|
43 |
teasePartition();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
}
|
45 |
|
46 |
function updateTagsConcatenated() {
|
@@ -71,35 +103,37 @@ function updateFooter() {
|
|
71 |
}
|
72 |
|
73 |
function loadEditedArtists() {
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
|
|
|
|
88 |
}
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
}
|
98 |
}
|
99 |
}
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
}
|
104 |
}
|
105 |
|
@@ -311,73 +345,81 @@ function insertCheckboxesFromCategories() {
|
|
311 |
}
|
312 |
|
313 |
function loadCheckboxesState() {
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
document.querySelector('input[name="'+name+'"]')
|
319 |
-
|
320 |
-
if(
|
321 |
-
|
|
|
|
|
322 |
}
|
323 |
}
|
324 |
}
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
}
|
329 |
}
|
330 |
|
331 |
function storeCheckboxState(checkbox) {
|
332 |
-
|
333 |
-
|
334 |
-
|
|
|
|
|
335 |
}
|
336 |
|
337 |
function storeCheckboxStateAll(isChecked) {
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
|
|
|
|
348 |
}
|
349 |
-
}
|
350 |
-
|
351 |
-
|
352 |
}
|
353 |
|
354 |
function loadOptionsState() {
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
360 |
imgTypeShown = 0;
|
361 |
-
} else if(state['prompt'] == 'promptP') {
|
362 |
-
imgTypeShown = 1;
|
363 |
-
} else if(state['prompt'] == 'promptL') {
|
364 |
-
imgTypeShown = 2;
|
365 |
}
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
document.getElementById(state['tagSort']).classList.add('selected');
|
379 |
-
} else {
|
380 |
-
// sortTC is already highlighted by HTML
|
381 |
}
|
382 |
}
|
383 |
|
@@ -424,25 +466,27 @@ function highlightSelectedOption(selected) {
|
|
424 |
}
|
425 |
|
426 |
function storeOptionsState() {
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
|
|
|
|
|
|
444 |
}
|
445 |
-
localStorage.setItem('tagsChecked', JSON.stringify(state));
|
446 |
}
|
447 |
|
448 |
function rotatePromptsImages() {
|
@@ -777,22 +821,26 @@ function showExport() {
|
|
777 |
document.getElementById('export').classList.add('shown');
|
778 |
// favorites
|
779 |
var textareaF = document.getElementById('export_favorites_list');
|
780 |
-
var
|
781 |
-
|
782 |
-
|
783 |
-
value
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
if(
|
788 |
-
|
|
|
|
|
|
|
789 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
790 |
}
|
791 |
-
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). It must not contain any other more than one set of curly brackets.\r\n\r\n' + favorites;
|
792 |
-
textareaF.value = value;
|
793 |
-
} else {
|
794 |
-
value += 'You haven\'t favorited any artists yet.\r\n\r\n';
|
795 |
-
value += 'To import favorites that you exported earlier, paste the text into this text box, and click "import".';
|
796 |
}
|
797 |
// edits
|
798 |
var textareaE = document.getElementById('export_edits_list');
|
@@ -836,42 +884,44 @@ function exportTextarea(type) {
|
|
836 |
}
|
837 |
|
838 |
function importFavorites() {
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
let
|
859 |
-
|
860 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
861 |
return null;
|
862 |
}
|
863 |
-
}
|
864 |
-
|
865 |
-
localStorage.setItem('favoritedArtists', jsonString);
|
866 |
-
alert('Favorites were imported!');
|
867 |
-
loadFavoritesState();
|
868 |
-
} else {
|
869 |
-
alert('Okay, you have cancelled the import.');
|
870 |
return null;
|
871 |
}
|
872 |
-
} catch(e) {
|
873 |
-
el.value = 'That text can\'t be imported because it doesn\'t contain a valid JSON sting.'
|
874 |
-
return null;
|
875 |
}
|
876 |
}
|
877 |
|
@@ -1048,20 +1098,22 @@ function sortTagsByCount() {
|
|
1048 |
}
|
1049 |
|
1050 |
function loadMostUsedTags() {
|
1051 |
-
|
1052 |
-
|
1053 |
-
|
1054 |
-
|
1055 |
-
|
1056 |
-
|
1057 |
-
label
|
1058 |
-
|
1059 |
-
|
1060 |
-
|
1061 |
-
|
|
|
|
|
1062 |
}
|
1063 |
-
}
|
1064 |
-
}
|
1065 |
}
|
1066 |
|
1067 |
function updateTagArrayToMatchMostUsed(isAdding,label,tag) {
|
@@ -1093,42 +1145,48 @@ function updateTagArrayToMatchMostUsed(isAdding,label,tag) {
|
|
1093 |
}
|
1094 |
|
1095 |
function storeMostUsedState(label) {
|
1096 |
-
|
1097 |
-
|
1098 |
-
|
1099 |
-
|
|
|
|
|
1100 |
}
|
1101 |
|
1102 |
function enterExitEditMostUsedMode(doExit) {
|
1103 |
-
|
1104 |
-
|
1105 |
-
|
1106 |
-
|
1107 |
-
|
1108 |
-
|
1109 |
-
|
1110 |
-
input
|
1111 |
-
|
1112 |
-
|
1113 |
-
|
1114 |
-
|
1115 |
-
|
1116 |
-
|
1117 |
-
|
1118 |
-
|
1119 |
-
|
1120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1121 |
} else {
|
1122 |
-
|
1123 |
-
editMostUsedMode = true;
|
1124 |
-
document.getElementById('edit_most_used').textContent = 'exit editing';
|
1125 |
-
document.getElementById('layout').classList.add('edit_mode');
|
1126 |
-
inputs.forEach(function(input) {
|
1127 |
-
input.disabled = true;
|
1128 |
-
});
|
1129 |
-
document.getElementById('toggles').style.width = '';
|
1130 |
-
document.getElementById('gutter').style.left = '';
|
1131 |
-
document.getElementById('image-container').style.marginLeft = '';
|
1132 |
}
|
1133 |
}
|
1134 |
|
@@ -1205,25 +1263,31 @@ function addOrRemoveFavorite(artist) {
|
|
1205 |
}
|
1206 |
|
1207 |
function loadFavoritesState() {
|
1208 |
-
|
1209 |
-
|
1210 |
-
|
1211 |
-
let
|
1212 |
-
|
1213 |
-
|
1214 |
-
|
1215 |
-
|
|
|
|
|
1216 |
}
|
|
|
1217 |
}
|
1218 |
-
updateFavoritesCount();
|
1219 |
}
|
1220 |
|
1221 |
function storeFavoriteState(artist) {
|
1222 |
-
|
1223 |
-
|
1224 |
-
|
1225 |
-
|
1226 |
-
|
|
|
|
|
|
|
|
|
1227 |
}
|
1228 |
|
1229 |
function updateFavoritesCount() {
|
@@ -1482,15 +1546,19 @@ function teasePartition() {
|
|
1482 |
}
|
1483 |
|
1484 |
function editTagsClicked(clickedImageItem) {
|
1485 |
-
|
1486 |
-
|
1487 |
-
|
1488 |
-
|
1489 |
-
|
|
|
|
|
|
|
|
|
|
|
1490 |
}
|
1491 |
-
editTagsEnterEditMode(clickedImageItem);
|
1492 |
} else {
|
1493 |
-
|
1494 |
}
|
1495 |
}
|
1496 |
|
@@ -1679,67 +1747,71 @@ function focusInput(input) {
|
|
1679 |
}
|
1680 |
|
1681 |
function saveTagsForArtist(tagArea) {
|
1682 |
-
|
1683 |
-
|
1684 |
-
|
1685 |
-
|
1686 |
-
|
1687 |
-
|
1688 |
-
|
1689 |
-
|
1690 |
-
|
1691 |
-
|
1692 |
-
|
1693 |
-
|
1694 |
-
}
|
1695 |
-
});
|
1696 |
-
// find match in artistsData
|
1697 |
-
let firstN = tagArea.closest('.image-item').querySelector('.firstN').textContent;
|
1698 |
-
let lastN = tagArea.closest('.image-item').querySelector('.lastN').textContent;
|
1699 |
-
let edit = [];
|
1700 |
-
for (let i=0, il=artistsData.length; i<il; i++) {
|
1701 |
-
let artist = artistsData[i];
|
1702 |
-
if(artist[0] == lastN && artist[1] == firstN) {
|
1703 |
-
// artists can have a tag in the format of "added-YYYY-MM-DD"
|
1704 |
-
// this was stripped earlier, so we need to add it back in
|
1705 |
-
let oldTagsArr = artist[2].split('|');
|
1706 |
-
for (let j=oldTagsArr.length-1; j>=0; j--) {
|
1707 |
-
// loop backwards because it should be at the end
|
1708 |
-
if(oldTagsArr[j].match(/added-(\d|-)*/)) {
|
1709 |
-
newTagsArr.push(oldTagsArr[j]);
|
1710 |
}
|
1711 |
}
|
1712 |
-
|
1713 |
-
|
1714 |
-
|
1715 |
-
|
1716 |
-
|
1717 |
-
|
1718 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1719 |
}
|
1720 |
-
edit = artist;
|
1721 |
-
break;
|
1722 |
}
|
1723 |
-
|
1724 |
-
|
1725 |
-
|
1726 |
-
|
1727 |
-
|
1728 |
-
|
1729 |
}
|
|
|
|
|
|
|
1730 |
}
|
1731 |
-
editedArtists.add(edit)
|
1732 |
-
// save edited artists locally
|
1733 |
-
localStorage.setItem('editedArtists', JSON.stringify(Array.from(editedArtists)));
|
1734 |
}
|
1735 |
|
1736 |
function deleteAllEdits() {
|
1737 |
-
if(
|
1738 |
-
|
1739 |
-
|
1740 |
-
|
1741 |
-
|
1742 |
-
|
|
|
|
|
1743 |
}
|
1744 |
}
|
1745 |
//
|
|
|
15 |
var startUpTime;
|
16 |
var tagsConcatenated = new Set();
|
17 |
var editedArtists = new Set();
|
18 |
+
var localStorageAccess = false;
|
19 |
//
|
20 |
//
|
21 |
//
|
22 |
// functions
|
23 |
function startUp() {
|
24 |
+
checkLocalStorageAccess();
|
25 |
updateTagsConcatenated();
|
26 |
updateFooter();
|
27 |
loadEditedArtists();
|
|
|
43 |
showHideLowCountTags();
|
44 |
makeStyleRuleForDrag();
|
45 |
teasePartition();
|
46 |
+
localStorageAccess = false;
|
47 |
+
alertNoLocalStorage(2000);
|
48 |
+
}
|
49 |
+
|
50 |
+
function checkLocalStorageAccess() {
|
51 |
+
try {
|
52 |
+
localStorage.setItem('testKey', 'testValue');
|
53 |
+
localStorage.removeItem('testKey');
|
54 |
+
localStorageAccess = true;
|
55 |
+
} catch (error) {
|
56 |
+
localStorageAccess = false;
|
57 |
+
alertNoLocalStorage();
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
function alertNoLocalStorage(wait) {
|
62 |
+
if(!localStorageAccess) {
|
63 |
+
window.setTimeout(function(){
|
64 |
+
let msg = '';
|
65 |
+
msg += 'My apologies, your browser settings block the ability to save settings and favorites. If you want those features, you have 3 options:\n';
|
66 |
+
msg += '1. Use a different browser than Chrome\n'
|
67 |
+
msg += '2. Change Chrome settings\n';
|
68 |
+
msg += '3. Download the app to use offline\n\n';
|
69 |
+
msg += 'This app doesn\'t use cookies and instead saves all settings locally so that no data is ever sent to any server. But when you set to Chrome to block third-party cookies (which you should), it stupidly also blocks local storage. That\'s because Google wants you to feel pain for blocking their ad-based revenue model. To change this setting in Chrome (not recommended):\n';
|
70 |
+
msg += '1. In settings, click "Privacy and security"\n';
|
71 |
+
msg += '2. Click "Third-party cookies" and set it to "Allow third-party cookies"\n';
|
72 |
+
msg += '3. Unfortunately, that will allow all 3rd-party cookies on all sites, which is exactly what Google wants.\n';
|
73 |
+
alert(msg);
|
74 |
+
},wait);
|
75 |
+
}
|
76 |
}
|
77 |
|
78 |
function updateTagsConcatenated() {
|
|
|
103 |
}
|
104 |
|
105 |
function loadEditedArtists() {
|
106 |
+
if(localStorageAccess) {
|
107 |
+
const arr = JSON.parse(localStorage.getItem('editedArtists')) || [];
|
108 |
+
editedArtists = new Set(arr);
|
109 |
+
let proto = window.location.protocol;
|
110 |
+
let anyChanges = false;
|
111 |
+
for (let i=0, il=artistsData.length; i<il; i++) {
|
112 |
+
// find match in artistsData if first and last names match
|
113 |
+
let artist = artistsData[i];
|
114 |
+
let artistFound = Array.from(editedArtists).find(editedA => editedA[0] === artist[0] && editedA[1] === artist[1]);
|
115 |
+
if(artistFound) {
|
116 |
+
// check if the edit now matches the original
|
117 |
+
let match = true;
|
118 |
+
for (let j=0, jl=artist.length; j<jl; j++) {
|
119 |
+
if (artist[j] !== artistFound[j]) {
|
120 |
+
match = false;
|
121 |
+
}
|
122 |
}
|
123 |
+
if(match) {
|
124 |
+
anyChanges = true;
|
125 |
+
editedArtists.delete(artistFound);
|
126 |
+
} else {
|
127 |
+
if (!proto.startsWith('http')) {
|
128 |
+
// if this is a local file, then update artistData with the saved edits
|
129 |
+
artistsData[i] = artistFound;
|
130 |
+
}
|
131 |
}
|
132 |
}
|
133 |
}
|
134 |
+
if(anyChanges) {
|
135 |
+
localStorage.setItem('editedArtists', JSON.stringify(Array.from(editedArtists)));
|
136 |
+
}
|
137 |
}
|
138 |
}
|
139 |
|
|
|
345 |
}
|
346 |
|
347 |
function loadCheckboxesState() {
|
348 |
+
if(localStorageAccess) {
|
349 |
+
let state = JSON.parse(localStorage.getItem('tagsChecked')) || {};
|
350 |
+
let allChecked = true;
|
351 |
+
for (let name in state) {
|
352 |
+
if (document.querySelector('input[name="'+name+'"]')) {
|
353 |
+
document.querySelector('input[name="'+name+'"]').checked = state[name];
|
354 |
+
if(name != 'mode' && name != 'use_categories') {
|
355 |
+
if(!state[name]) {
|
356 |
+
allChecked = false;
|
357 |
+
}
|
358 |
}
|
359 |
}
|
360 |
}
|
361 |
+
if(!allChecked) {
|
362 |
+
document.querySelector('input[name="check-all"]').checked = false;
|
363 |
+
}
|
364 |
}
|
365 |
}
|
366 |
|
367 |
function storeCheckboxState(checkbox) {
|
368 |
+
if(localStorageAccess) {
|
369 |
+
let state = JSON.parse(localStorage.getItem('tagsChecked')) || {};
|
370 |
+
state[checkbox.name] = checkbox.checked;
|
371 |
+
localStorage.setItem('tagsChecked', JSON.stringify(state));
|
372 |
+
}
|
373 |
}
|
374 |
|
375 |
function storeCheckboxStateAll(isChecked) {
|
376 |
+
if(localStorageAccess) {
|
377 |
+
let state = {};
|
378 |
+
var checkboxes = document.querySelectorAll('input[type="checkbox"]');
|
379 |
+
checkboxes.forEach(function(checkbox) {
|
380 |
+
let isTop = checkbox.parentNode.classList.contains('top_control');
|
381 |
+
if(!isTop || checkbox.name == 'favorite') {
|
382 |
+
// is a tag checkbox, not a setting
|
383 |
+
if(isChecked) {
|
384 |
+
state[checkbox.name] = true;
|
385 |
+
} else {
|
386 |
+
state[checkbox.name] = false;
|
387 |
+
}
|
388 |
}
|
389 |
+
});
|
390 |
+
localStorage.setItem('tagsChecked', JSON.stringify(state));
|
391 |
+
}
|
392 |
}
|
393 |
|
394 |
function loadOptionsState() {
|
395 |
+
if(localStorageAccess) {
|
396 |
+
let state = JSON.parse(localStorage.getItem('tagsChecked')) || {};
|
397 |
+
if(state['prompt']) {
|
398 |
+
document.getElementById('options_prompts').querySelectorAll('.selected')[0].classList.remove('selected');
|
399 |
+
document.getElementById(state['prompt']).classList.add('selected');
|
400 |
+
if(state['prompt'] == 'promptA') {
|
401 |
+
imgTypeShown = 0;
|
402 |
+
} else if(state['prompt'] == 'promptP') {
|
403 |
+
imgTypeShown = 1;
|
404 |
+
} else if(state['prompt'] == 'promptL') {
|
405 |
+
imgTypeShown = 2;
|
406 |
+
}
|
407 |
+
} else {
|
408 |
+
// promptA is already highlighted by HTML
|
409 |
imgTypeShown = 0;
|
|
|
|
|
|
|
|
|
410 |
}
|
411 |
+
if(state['artistSort']) {
|
412 |
+
document.getElementById('options_artist_sort').querySelectorAll('.selected')[0].classList.remove('selected');
|
413 |
+
document.getElementById(state['artistSort']).classList.add('selected');
|
414 |
+
} else {
|
415 |
+
// sortAR is already highlighted by HTML
|
416 |
+
}
|
417 |
+
if(state['tagSort']) {
|
418 |
+
document.getElementById('options_tag_sort').querySelectorAll('.selected')[0].classList.remove('selected');
|
419 |
+
document.getElementById(state['tagSort']).classList.add('selected');
|
420 |
+
} else {
|
421 |
+
// sortTC is already highlighted by HTML
|
422 |
+
}
|
|
|
|
|
|
|
423 |
}
|
424 |
}
|
425 |
|
|
|
466 |
}
|
467 |
|
468 |
function storeOptionsState() {
|
469 |
+
if(localStorageAccess) {
|
470 |
+
let state = JSON.parse(localStorage.getItem('tagsChecked')) || {};
|
471 |
+
if(document.getElementById('promptA').classList.contains('selected')) {
|
472 |
+
state['prompt'] = 'promptA';
|
473 |
+
} else if(document.getElementById('promptP').classList.contains('selected')) {
|
474 |
+
state['prompt'] = 'promptP';
|
475 |
+
} else {
|
476 |
+
state['prompt'] = 'promptL';
|
477 |
+
}
|
478 |
+
if(document.getElementById('sortAR').classList.contains('selected')) {
|
479 |
+
state['artistSort'] = 'sortAR';
|
480 |
+
} else {
|
481 |
+
state['artistSort'] = 'sortAA';
|
482 |
+
}
|
483 |
+
if(document.getElementById('sortTC').classList.contains('selected')) {
|
484 |
+
state['tagSort'] = 'sortTC';
|
485 |
+
} else {
|
486 |
+
state['tagSort'] = 'sortTA';
|
487 |
+
}
|
488 |
+
localStorage.setItem('tagsChecked', JSON.stringify(state));
|
489 |
}
|
|
|
490 |
}
|
491 |
|
492 |
function rotatePromptsImages() {
|
|
|
821 |
document.getElementById('export').classList.add('shown');
|
822 |
// favorites
|
823 |
var textareaF = document.getElementById('export_favorites_list');
|
824 |
+
var favoritedArtists = false;
|
825 |
+
if(localStorageAccess) {
|
826 |
+
var favorites = localStorage.getItem('favoritedArtists');
|
827 |
+
var value = '';
|
828 |
+
if(favorites) {
|
829 |
+
value += 'You have favorited these artists:\r\n';
|
830 |
+
for (let key in JSON.parse(favorites)) {
|
831 |
+
if (JSON.parse(favorites)[key] === true) {
|
832 |
+
let names = key.split("|");
|
833 |
+
if(!names[0]) { names[0] = '(no first name)'; }
|
834 |
+
value += '•' + names[0] + ',' + names[1] + '\r\n';
|
835 |
+
}
|
836 |
}
|
837 |
+
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). It must not contain any other more than one set of curly brackets.\r\n\r\n' + favorites;
|
838 |
+
textareaF.value = value;
|
839 |
+
} else {
|
840 |
+
value += 'You haven\'t favorited any artists yet.\r\n\r\n';
|
841 |
+
value += 'To import favorites that you exported earlier, paste the text into this text box, and click "import".';
|
842 |
+
textareaF.value = value;
|
843 |
}
|
|
|
|
|
|
|
|
|
|
|
844 |
}
|
845 |
// edits
|
846 |
var textareaE = document.getElementById('export_edits_list');
|
|
|
884 |
}
|
885 |
|
886 |
function importFavorites() {
|
887 |
+
if(localStorageAccess) {
|
888 |
+
let el = document.getElementById('export_favorites_list');
|
889 |
+
let favorites = el.value;
|
890 |
+
let startCount = (favorites.match(/{/g) || []).length;
|
891 |
+
let endCount = (favorites.match(/}/g) || []).length;
|
892 |
+
if (startCount > 1 || endCount > 1) {
|
893 |
+
el.value = 'That text can\'t be imported because it contains multiple curly brackets {}.'
|
894 |
+
return null;
|
895 |
+
}
|
896 |
+
let start = favorites.indexOf('{');
|
897 |
+
let end = favorites.lastIndexOf('}');
|
898 |
+
if (start === -1 || end === -1) {
|
899 |
+
el.value = 'That text can\'t be imported because it contains zero curly brackets {}.'
|
900 |
+
return null;
|
901 |
+
}
|
902 |
+
let jsonString = favorites.substring(start, end + 1);
|
903 |
+
try {
|
904 |
+
let jsonObject = JSON.parse(jsonString);
|
905 |
+
// Check structure of each key-value pair in jsonObject
|
906 |
+
for (let key in jsonObject) {
|
907 |
+
let value = jsonObject[key];
|
908 |
+
if (!key.includes('|') || typeof value !== 'boolean') {
|
909 |
+
el.value = 'That text can\'t be imported because the JSON string it contains doesn\'t contain a valid list of artists.'
|
910 |
+
return null;
|
911 |
+
}
|
912 |
+
}
|
913 |
+
if(confirm('This will overwrite any saved favorites. Are you sure?')) {
|
914 |
+
localStorage.setItem('favoritedArtists', jsonString);
|
915 |
+
alert('Favorites were imported!');
|
916 |
+
loadFavoritesState();
|
917 |
+
} else {
|
918 |
+
alert('Okay, you have cancelled the import.');
|
919 |
return null;
|
920 |
}
|
921 |
+
} catch(e) {
|
922 |
+
el.value = 'That text can\'t be imported because it doesn\'t contain a valid JSON sting.'
|
|
|
|
|
|
|
|
|
|
|
923 |
return null;
|
924 |
}
|
|
|
|
|
|
|
925 |
}
|
926 |
}
|
927 |
|
|
|
1098 |
}
|
1099 |
|
1100 |
function loadMostUsedTags() {
|
1101 |
+
if(localStorageAccess) {
|
1102 |
+
let state = JSON.parse(localStorage.getItem('mustUsedTags')) || {};
|
1103 |
+
let mostUsedCategory = document.querySelector('[data-category-name="important"]');
|
1104 |
+
for(let tag in state) {
|
1105 |
+
if (state[tag]) {
|
1106 |
+
let label = document.querySelector('input[name="'+ tag +'"]');
|
1107 |
+
if(label) {
|
1108 |
+
label = label.parentNode;
|
1109 |
+
label.classList.add('is_most_used');
|
1110 |
+
label.querySelectorAll('.most_used_indicator')[0].textContent = '-';
|
1111 |
+
mostUsedCategory.after(label);
|
1112 |
+
updateTagArrayToMatchMostUsed(true,label,tag);
|
1113 |
+
}
|
1114 |
}
|
1115 |
+
};
|
1116 |
+
}
|
1117 |
}
|
1118 |
|
1119 |
function updateTagArrayToMatchMostUsed(isAdding,label,tag) {
|
|
|
1145 |
}
|
1146 |
|
1147 |
function storeMostUsedState(label) {
|
1148 |
+
if(localStorageAccess) {
|
1149 |
+
var name = label.querySelector('input').name;
|
1150 |
+
let state = JSON.parse(localStorage.getItem('mustUsedTags')) || {};
|
1151 |
+
state[name] = label.classList.contains('is_most_used');
|
1152 |
+
localStorage.setItem('mustUsedTags', JSON.stringify(state));
|
1153 |
+
}
|
1154 |
}
|
1155 |
|
1156 |
function enterExitEditMostUsedMode(doExit) {
|
1157 |
+
if(localStorageAccess) {
|
1158 |
+
let inputs = Array.from(document.querySelectorAll('input'));
|
1159 |
+
if(editMostUsedMode || doExit) {
|
1160 |
+
// exit edit mode
|
1161 |
+
editMostUsedMode = false;
|
1162 |
+
document.getElementById('edit_most_used').textContent = 'edit';
|
1163 |
+
document.getElementById('layout').classList.remove('edit_mode');
|
1164 |
+
inputs.forEach(function(input) {
|
1165 |
+
input.disabled = false;
|
1166 |
+
});
|
1167 |
+
let labels = Array.from(document.querySelectorAll('.was_moved'));
|
1168 |
+
labels.forEach(function(label) {
|
1169 |
+
// clean up classes added to track moved tags during edit mode
|
1170 |
+
label.classList.remove('was_moved');
|
1171 |
+
})
|
1172 |
+
document.getElementById('toggles').style.width = 'calc(' + gutterEndPercentX + '% - 20px)';
|
1173 |
+
document.getElementById('gutter').style.left = gutterEndPercentX + '%';
|
1174 |
+
document.getElementById('image-container').style.marginLeft = 'calc(' + gutterEndPercentX + '% + 50px)';
|
1175 |
+
updateArtistsCountPerCategory();
|
1176 |
+
} else {
|
1177 |
+
// enter edit mode
|
1178 |
+
editMostUsedMode = true;
|
1179 |
+
document.getElementById('edit_most_used').textContent = 'exit editing';
|
1180 |
+
document.getElementById('layout').classList.add('edit_mode');
|
1181 |
+
inputs.forEach(function(input) {
|
1182 |
+
input.disabled = true;
|
1183 |
+
});
|
1184 |
+
document.getElementById('toggles').style.width = '';
|
1185 |
+
document.getElementById('gutter').style.left = '';
|
1186 |
+
document.getElementById('image-container').style.marginLeft = '';
|
1187 |
+
}
|
1188 |
} else {
|
1189 |
+
alertNoLocalStorage(0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1190 |
}
|
1191 |
}
|
1192 |
|
|
|
1263 |
}
|
1264 |
|
1265 |
function loadFavoritesState() {
|
1266 |
+
if(localStorageAccess) {
|
1267 |
+
let state = JSON.parse(localStorage.getItem('favoritedArtists')) || {};
|
1268 |
+
let artists = document.getElementsByClassName('image-item');
|
1269 |
+
for(let artist of artists) {
|
1270 |
+
let artistName = artist.getElementsByClassName('firstN')[0].textContent + '|' + artist.getElementsByClassName('lastN')[0].textContent;
|
1271 |
+
if(state[artistName]) {
|
1272 |
+
artist.classList.add('favorite');
|
1273 |
+
} else {
|
1274 |
+
artist.classList.remove('favorite');
|
1275 |
+
}
|
1276 |
}
|
1277 |
+
updateFavoritesCount();
|
1278 |
}
|
|
|
1279 |
}
|
1280 |
|
1281 |
function storeFavoriteState(artist) {
|
1282 |
+
if(localStorageAccess) {
|
1283 |
+
var artistName = artist.getElementsByClassName('firstN')[0].textContent + '|' + artist.getElementsByClassName('lastN')[0].textContent;
|
1284 |
+
var isFavorited = artist.classList.contains('favorite');
|
1285 |
+
let state = JSON.parse(localStorage.getItem('favoritedArtists')) || {};
|
1286 |
+
state[artistName] = isFavorited;
|
1287 |
+
localStorage.setItem('favoritedArtists', JSON.stringify(state));
|
1288 |
+
} else {
|
1289 |
+
alertNoLocalStorage(0);
|
1290 |
+
}
|
1291 |
}
|
1292 |
|
1293 |
function updateFavoritesCount() {
|
|
|
1546 |
}
|
1547 |
|
1548 |
function editTagsClicked(clickedImageItem) {
|
1549 |
+
if(localStorageAccess) {
|
1550 |
+
let indicatorEl = clickedImageItem.querySelector('.art_edit span');
|
1551 |
+
if(indicatorEl.textContent == '✍️') {
|
1552 |
+
let artistWasInEditMode = editTagsFindArtistInEditMode(clickedImageItem);
|
1553 |
+
if(!artistWasInEditMode) {
|
1554 |
+
doAlert('Read help ⁉️ first',1);
|
1555 |
+
}
|
1556 |
+
editTagsEnterEditMode(clickedImageItem);
|
1557 |
+
} else {
|
1558 |
+
editTagsFindArtistInEditMode();
|
1559 |
}
|
|
|
1560 |
} else {
|
1561 |
+
alertNoLocalStorage(0);
|
1562 |
}
|
1563 |
}
|
1564 |
|
|
|
1747 |
}
|
1748 |
|
1749 |
function saveTagsForArtist(tagArea) {
|
1750 |
+
if(localStorageAccess) {
|
1751 |
+
// get new tags
|
1752 |
+
let tagLabels = tagArea.querySelectorAll('label');
|
1753 |
+
let newTagsArr = [];
|
1754 |
+
let artistKnown = true;
|
1755 |
+
tagLabels.forEach(function(label) {
|
1756 |
+
let input = label.querySelector('input');
|
1757 |
+
if(input.value == 'known') {
|
1758 |
+
artistKnown = input.checked;
|
1759 |
+
} else {
|
1760 |
+
if(input.checked) {
|
1761 |
+
newTagsArr.push(input.value);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1762 |
}
|
1763 |
}
|
1764 |
+
});
|
1765 |
+
// find match in artistsData
|
1766 |
+
let firstN = tagArea.closest('.image-item').querySelector('.firstN').textContent;
|
1767 |
+
let lastN = tagArea.closest('.image-item').querySelector('.lastN').textContent;
|
1768 |
+
let edit = [];
|
1769 |
+
for (let i=0, il=artistsData.length; i<il; i++) {
|
1770 |
+
let artist = artistsData[i];
|
1771 |
+
if(artist[0] == lastN && artist[1] == firstN) {
|
1772 |
+
// artists can have a tag in the format of "added-YYYY-MM-DD"
|
1773 |
+
// this was stripped earlier, so we need to add it back in
|
1774 |
+
let oldTagsArr = artist[2].split('|');
|
1775 |
+
for (let j=oldTagsArr.length-1; j>=0; j--) {
|
1776 |
+
// loop backwards because it should be at the end
|
1777 |
+
if(oldTagsArr[j].match(/added-(\d|-)*/)) {
|
1778 |
+
newTagsArr.push(oldTagsArr[j]);
|
1779 |
+
}
|
1780 |
+
}
|
1781 |
+
let newTagsStr = newTagsArr.join('|');
|
1782 |
+
artist[2] = newTagsStr;
|
1783 |
+
// in db, true = hide unknown, but here true = known
|
1784 |
+
if(artistKnown) {
|
1785 |
+
artist[3] = false;
|
1786 |
+
} else {
|
1787 |
+
artist[3] = true;
|
1788 |
+
}
|
1789 |
+
edit = artist;
|
1790 |
+
break;
|
1791 |
}
|
|
|
|
|
1792 |
}
|
1793 |
+
// replace old edits with new edits
|
1794 |
+
for (let i=0, il=editedArtists.length; i<il; i++) {
|
1795 |
+
let oldEdit = editedArtists[i];
|
1796 |
+
if(edit[0] == oldEdit[0] && edit[1] == oldEdit[1]) {
|
1797 |
+
editedArtists.delete(oldEdit);
|
1798 |
+
}
|
1799 |
}
|
1800 |
+
editedArtists.add(edit)
|
1801 |
+
// save edited artists locally
|
1802 |
+
localStorage.setItem('editedArtists', JSON.stringify(Array.from(editedArtists)));
|
1803 |
}
|
|
|
|
|
|
|
1804 |
}
|
1805 |
|
1806 |
function deleteAllEdits() {
|
1807 |
+
if(localStorageAccess) {
|
1808 |
+
if(confirm('This will delete all of your edits. Are you sure?')) {
|
1809 |
+
localStorage.removeItem('editedArtists');
|
1810 |
+
alert('official database restored! this page will reload...');
|
1811 |
+
location.reload();
|
1812 |
+
} else {
|
1813 |
+
alert('restore was cancelled!');
|
1814 |
+
}
|
1815 |
}
|
1816 |
}
|
1817 |
//
|