Skip to content

Commit 6292b00

Browse files
committed
[tagCopyPaste] add native copy/paste support
- clean up function definitions, compress long string with variables - clean up iterating for loops without indicies
1 parent 4ccbf2f commit 6292b00

File tree

2 files changed

+63
-96
lines changed

2 files changed

+63
-96
lines changed

plugins/tagCopyPaste/tagCopyPaste.js

Lines changed: 62 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
requireConfirmation: false,
66
};
77

8+
// helper function to get the innerText of all elements matching a selector
9+
const getAllInnerText = (selector) => Array.from(document.querySelectorAll(selector))
10+
.map((el) => el.innerText)
11+
.filter((text) => text.trim() !== "");
12+
813
// On image page, get data about gallery (image's position within gallery, next/prev image IDs),
914
// add arrow buttons to page, and register arrow keypress handlers,
1015
async function setupTagCopyPaste(objType) {
@@ -24,21 +29,31 @@
2429
}
2530

2631
function insertCopyPasteButtons(objID, objType) {
32+
// listen for copy and paste events within tag input box
33+
// find tag input box
34+
const tagInputBox = document.querySelector("label[for='tag_ids'] + div .react-select__value-container");
35+
if (tagInputBox) {
36+
tagInputBox.addEventListener("copy", (event) => {
37+
event.preventDefault();
38+
console.log("Copy event triggered");
39+
handleCopyClick();
40+
});
41+
tagInputBox.addEventListener("paste", (event) => {
42+
event.preventDefault();
43+
console.log("Paste event triggered");
44+
handlePasteClick(objID, objType);
45+
});
46+
}
47+
2748
var copyButton = document.createElement("button");
2849
copyButton.className = "imageGalleryNav-copyButton btn btn-secondary";
2950
copyButton.innerText = "Copy";
30-
copyButton.addEventListener("click", (e) => {
31-
e.preventDefault();
32-
handleCopyClick();
33-
});
51+
copyButton.onclick = () => handleCopyClick();
3452

3553
var pasteButton = document.createElement("button");
3654
pasteButton.className = "imageGalleryNav-pasteButton btn btn-secondary";
3755
pasteButton.innerText = "Paste";
38-
pasteButton.addEventListener("click", (e) => {
39-
e.preventDefault();
40-
handlePasteClick(objID, objType);
41-
});
56+
pasteButton.onclick = () => handlePasteClick(objID, objType);
4257

4358
if (document.querySelector("button.imageGalleryNav-pasteButton") == null) {
4459
document.querySelector("label[for='tag_ids']").append(pasteButton);
@@ -50,99 +65,66 @@
5065

5166
// Handle copy click. Return delimited list of current tags.
5267
async function handleCopyClick() {
53-
// Get tags from input box.
54-
var tagList = [];
55-
document
56-
.querySelectorAll(
57-
"label[for='tag_ids'] + div .react-select__multi-value__label"
58-
)
59-
.forEach((item) => {
60-
tagList.push(item.innerText);
61-
});
62-
63-
// Join tags as comma delimited list and write to clipboard.
64-
await navigator.clipboard.writeText(tagList.join(","));
68+
// Get tags from input box
69+
// join as comma delimited list
70+
const tagList = getAllInnerText("label[for='tag_ids'] + div .react-select__multi-value__label").join(",")
71+
// write to clipboard.
72+
navigator.clipboard.writeText(tagList);
6573
}
6674

6775
// Handle paste click.
6876
async function handlePasteClick(objID, objType) {
69-
var inputTagList = [];
70-
7177
// Parse tag list from comma delimited string.
72-
var tagInput = await navigator.clipboard.readText();
73-
tagInput.split(",").forEach((item) => {
74-
if (!inputTagList.includes(item)) {
75-
inputTagList.push(item);
76-
}
77-
});
78+
const tagInput = await navigator.clipboard.readText();
79+
var inputTagList = tagInput.split(",") // do de-duplication later
7880

7981
// Get tags from input box and also add to tag list.
80-
document
81-
.querySelectorAll(
82-
"label[for='tag_ids'] + div .react-select__multi-value__label"
83-
)
84-
.forEach((item) => {
85-
if (!inputTagList.includes(item)) {
86-
inputTagList.push(item.innerText);
87-
}
88-
});
82+
const existingTagList = ("label[for='tag_ids'] + div .react-select__multi-value__label")
8983

90-
inputTagList.sort();
84+
inputTagList = [...new Set([...inputTagList, ...existingTagList])].sort();
9185

9286
var missingTags = [];
9387
var existingTags = [];
9488
var tagUpdateList = [];
9589

9690
// Search for tag ID for each tag. If exists, add to tag ID list. If not exists, create new tag and add to tag ID list.
97-
for (let i = 0; i < inputTagList.length; i++) {
98-
var inputTag = inputTagList[i];
99-
var tagID = await getTagByName(inputTag);
100-
if (tagID != null && tagID.length) {
91+
for (const inputTag of inputTagList) {
92+
const tagID = await getTagByName(inputTag.trim());
93+
if (tagID) {
10194
existingTags.push(inputTag);
10295
tagUpdateList.push(tagID[0]);
10396
} else {
10497
missingTags.push(inputTag);
10598
}
10699
}
107100

101+
108102
if (pluginSettings.requireConfirmation) {
109-
var msg = "";
110-
if (pluginSettings.createIfNotExists) {
111-
msg = `Missing Tags that will be created:\n${missingTags.join(
112-
", "
113-
)}\n\nExisting Tags that will be saved: \n${existingTags.join(
114-
", "
115-
)}\n\nContinue?`;
116-
} else {
117-
msg = `Missing Tags that will be skipped:\n${missingTags.join(
118-
", "
119-
)}\n\nExisting Tags that will be saved: \n${existingTags.join(
120-
", "
121-
)}\n\nContinue?`;
122-
}
123103

124-
var userConfirmed = confirm(msg);
125-
if (!userConfirmed) {
104+
const missingTagsStr = missingTags.join(", ");
105+
const existingTagsStr = existingTags.join(", ");
106+
const msg = pluginSettings.createIfNotExists
107+
? `Missing Tags that will be created:\n${missingTagsStr}\n\nExisting Tags that will be saved: \n${existingTagsStr}\n\nContinue?`
108+
: `Missing Tags that will be skipped:\n${missingTagsStr}\n\nExisting Tags that will be saved: \n${existingTagsStr}\n\nContinue?`;
109+
110+
if (!confirm(msg)) {
126111
return;
127112
}
128113
}
129114

130115
if (pluginSettings.createIfNotExists && missingTags.length) {
131-
for (let i = 0; i < missingTags.length; i++) {
132-
var newTagName = missingTags[i];
133-
var newTagID = await createNewTag(newTagName);
134-
if (newTagID != null) {
135-
tagUpdateList.push(newTagID);
136-
}
116+
for (const missingTag of missingTags) {
117+
const newTagID = await createNewTag(missingTag);
118+
if (newTagID != null) tagUpdateList.push(newTagID);
137119
}
138120
}
139121

140122
// Update tags on object with new tag ID list.
141123
await updateObjTags(
142124
objID,
143125
tagUpdateList,
144-
objType.toLowerCase() + "Update",
145-
objType + "UpdateInput"
126+
`${objType.toLowerCase()}Update`,
127+
`${objType}UpdateInput`
146128
);
147129

148130
window.location.reload();
@@ -183,33 +165,18 @@
183165
.then((data) => data.findTags.tags.map((item) => item.id));
184166
}
185167

186-
// Wait for scenes page.
187-
csLib.PathElementListener("/scenes/", "[id*='-edit-details']", () => {
188-
setupTagCopyPaste("Scene");
189-
}); // PathElementListener is from cs-ui-lib.js
190-
191-
// Wait for studios page.
192-
csLib.PathElementListener("/studios/", "[id='studio-edit']", () => {
193-
setupTagCopyPaste("Studio");
194-
}); // PathElementListener is from cs-ui-lib.js
195-
196-
// Wait for groups page.
197-
csLib.PathElementListener("/groups/", "[id='group-edit']", () => {
198-
setupTagCopyPaste("Group");
199-
}); // PathElementListener is from cs-ui-lib.js
200-
201-
// Wait for performers page.
202-
csLib.PathElementListener("/performers/", "[id='performer-edit']", () => {
203-
setupTagCopyPaste("Performer");
204-
}); // PathElementListener is from cs-ui-lib.js
205-
206-
// Wait for galleries page.
207-
csLib.PathElementListener("/galleries/", "[id*='-edit-details']", () => {
208-
setupTagCopyPaste("Gallery");
209-
}); // PathElementListener is from cs-ui-lib.js
210-
211-
// Wait for images page.
212-
csLib.PathElementListener("/images/", "[id*='-edit-details']", () => {
213-
setupTagCopyPaste("Image");
214-
}); // PathElementListener is from cs-ui-lib.js
168+
// listener arrays
169+
[
170+
[ "/scenes/", "[id*='-edit-details']", "Scene" ],
171+
[ "/studios/", "[id='studio-edit']", "Studio" ],
172+
[ "/groups/", "[id='group-edit']", "Group" ],
173+
[ "/performers/", "[id='performer-edit']", "Performer" ],
174+
[ "/galleries/", "[id*='-edit-details']", "Gallery" ],
175+
[ "/images/", "[id*='-edit-details']", "Image" ]
176+
].forEach(([path, selector, objType]) => {
177+
// Wait for the page to load and the element to be present.
178+
csLib.PathElementListener(path, selector, () => {
179+
setupTagCopyPaste(objType);
180+
}); // PathElementListener is from cs-ui-lib.js
181+
});
215182
})();

plugins/tagCopyPaste/tagCopyPaste.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: tagCopyPaste
22
# requires: CommunityScriptsUILibrary
33
description: Adds Copy/Paste buttons to Tags field.
4-
version: 0.1
4+
version: 0.2
55
settings:
66
createIfNotExists:
77
displayName: Create If Not Exists

0 commit comments

Comments
 (0)