mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-07-16 02:03:07 -07:00
WebUI: migrate away from inline HTML code
`innerHTML` & `outerHTML` setter will more or less evaluate the value which could be used to inject malicious code. So replace them with safer alternatives. PR #21163.
This commit is contained in:
parent
4570c0ef9e
commit
5afeecbf18
7 changed files with 201 additions and 114 deletions
|
@ -474,15 +474,26 @@ window.addEventListener("DOMContentLoaded", () => {
|
||||||
margin_left = (category_path.length - 1) * 20;
|
margin_left = (category_path.length - 1) * 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
const html = `<span class="link" href="#" style="margin-left: ${margin_left}px;" onclick="setCategoryFilter(${hash}); return false;">`
|
const span = document.createElement("span");
|
||||||
+ '<img src="images/view-categories.svg"/>'
|
span.classList.add("link");
|
||||||
+ window.qBittorrent.Misc.escapeHtml(display_name) + " (" + count + ")" + "</span>";
|
span.href = "#";
|
||||||
const el = new Element("li", {
|
span.style.marginLeft = `${margin_left}px`;
|
||||||
id: hash,
|
span.textContent = `${display_name} (${count})`;
|
||||||
html: html
|
span.addEventListener("click", (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
setCategoryFilter(hash);
|
||||||
});
|
});
|
||||||
window.qBittorrent.Filters.categoriesFilterContextMenu.addTarget(el);
|
|
||||||
return el;
|
const img = document.createElement("img");
|
||||||
|
img.src = "images/view-categories.svg";
|
||||||
|
span.prepend(img);
|
||||||
|
|
||||||
|
const listItem = document.createElement("li");
|
||||||
|
listItem.id = hash;
|
||||||
|
listItem.appendChild(span);
|
||||||
|
|
||||||
|
window.qBittorrent.Filters.categoriesFilterContextMenu.addTarget(listItem);
|
||||||
|
return listItem;
|
||||||
};
|
};
|
||||||
|
|
||||||
const all = torrentsTable.getRowIds().length;
|
const all = torrentsTable.getRowIds().length;
|
||||||
|
@ -555,15 +566,25 @@ window.addEventListener("DOMContentLoaded", () => {
|
||||||
tagFilterList.getChildren().each(c => c.destroy());
|
tagFilterList.getChildren().each(c => c.destroy());
|
||||||
|
|
||||||
const createLink = function(hash, text, count) {
|
const createLink = function(hash, text, count) {
|
||||||
const html = `<span class="link" href="#" onclick="setTagFilter(${hash}); return false;">`
|
const span = document.createElement("span");
|
||||||
+ '<img src="images/tags.svg"/>'
|
span.classList.add("link");
|
||||||
+ window.qBittorrent.Misc.escapeHtml(text) + " (" + count + ")" + "</span>";
|
span.href = "#";
|
||||||
const el = new Element("li", {
|
span.textContent = `${text} (${count})`;
|
||||||
id: hash,
|
span.addEventListener("click", (event) => {
|
||||||
html: html
|
event.preventDefault();
|
||||||
|
setTagFilter(hash);
|
||||||
});
|
});
|
||||||
window.qBittorrent.Filters.tagsFilterContextMenu.addTarget(el);
|
|
||||||
return el;
|
const img = document.createElement("img");
|
||||||
|
img.src = "images/tags.svg";
|
||||||
|
span.prepend(img);
|
||||||
|
|
||||||
|
const listItem = document.createElement("li");
|
||||||
|
listItem.id = hash;
|
||||||
|
listItem.appendChild(span);
|
||||||
|
|
||||||
|
window.qBittorrent.Filters.tagsFilterContextMenu.addTarget(listItem);
|
||||||
|
return listItem;
|
||||||
};
|
};
|
||||||
|
|
||||||
const torrentsCount = torrentsTable.getRowIds().length;
|
const torrentsCount = torrentsTable.getRowIds().length;
|
||||||
|
@ -631,15 +652,25 @@ window.addEventListener("DOMContentLoaded", () => {
|
||||||
trackerFilterList.getChildren().each(c => c.destroy());
|
trackerFilterList.getChildren().each(c => c.destroy());
|
||||||
|
|
||||||
const createLink = function(hash, text, count) {
|
const createLink = function(hash, text, count) {
|
||||||
const html = '<span class="link" href="#" onclick="setTrackerFilter(' + hash + ');return false;">'
|
const span = document.createElement("span");
|
||||||
+ '<img src="images/trackers.svg"/>'
|
span.classList.add("link");
|
||||||
+ window.qBittorrent.Misc.escapeHtml(text.replace("%1", count)) + "</span>";
|
span.href = "#";
|
||||||
const el = new Element("li", {
|
span.textContent = text.replace("%1", count);
|
||||||
id: hash,
|
span.addEventListener("click", (event) => {
|
||||||
html: html
|
event.preventDefault();
|
||||||
|
setTrackerFilter(hash);
|
||||||
});
|
});
|
||||||
window.qBittorrent.Filters.trackersFilterContextMenu.addTarget(el);
|
|
||||||
return el;
|
const img = document.createElement("img");
|
||||||
|
img.src = "images/trackers.svg";
|
||||||
|
span.prepend(img);
|
||||||
|
|
||||||
|
const listItem = document.createElement("li");
|
||||||
|
listItem.id = hash;
|
||||||
|
listItem.appendChild(span);
|
||||||
|
|
||||||
|
window.qBittorrent.Filters.trackersFilterContextMenu.addTarget(listItem);
|
||||||
|
return listItem;
|
||||||
};
|
};
|
||||||
|
|
||||||
const torrentsCount = torrentsTable.getRowIds().length;
|
const torrentsCount = torrentsTable.getRowIds().length;
|
||||||
|
|
|
@ -428,7 +428,7 @@ window.qBittorrent.ContextMenu ??= (() => {
|
||||||
|
|
||||||
const contextTagList = $("contextTagList");
|
const contextTagList = $("contextTagList");
|
||||||
tagList.forEach((tag, tagHash) => {
|
tagList.forEach((tag, tagHash) => {
|
||||||
const checkbox = contextTagList.getElement(`a[href="#Tag/${tagHash}"] input[type="checkbox"]`);
|
const checkbox = contextTagList.getElement(`a[href="#Tag/${tag.name}"] input[type="checkbox"]`);
|
||||||
const count = tagCount.get(tag.name);
|
const count = tagCount.get(tag.name);
|
||||||
const hasCount = (count !== undefined);
|
const hasCount = (count !== undefined);
|
||||||
const isLesser = (count < selectedRows.length);
|
const isLesser = (count < selectedRows.length);
|
||||||
|
@ -438,7 +438,7 @@ window.qBittorrent.ContextMenu ??= (() => {
|
||||||
|
|
||||||
const contextCategoryList = document.getElementById("contextCategoryList");
|
const contextCategoryList = document.getElementById("contextCategoryList");
|
||||||
category_list.forEach((category, categoryHash) => {
|
category_list.forEach((category, categoryHash) => {
|
||||||
const categoryIcon = contextCategoryList.querySelector(`a[href$="(${categoryHash});"] img`);
|
const categoryIcon = contextCategoryList.querySelector(`a[href$="#Category/${category.name}"] img`);
|
||||||
const count = categoryCount.get(category.name);
|
const count = categoryCount.get(category.name);
|
||||||
const isEqual = ((count !== undefined) && (count === selectedRows.length));
|
const isEqual = ((count !== undefined) && (count === selectedRows.length));
|
||||||
categoryIcon.classList.toggle("highlightedCategoryIcon", isEqual);
|
categoryIcon.classList.toggle("highlightedCategoryIcon", isEqual);
|
||||||
|
@ -448,12 +448,24 @@ window.qBittorrent.ContextMenu ??= (() => {
|
||||||
updateCategoriesSubMenu: function(categoryList) {
|
updateCategoriesSubMenu: function(categoryList) {
|
||||||
const contextCategoryList = $("contextCategoryList");
|
const contextCategoryList = $("contextCategoryList");
|
||||||
contextCategoryList.getChildren().each(c => c.destroy());
|
contextCategoryList.getChildren().each(c => c.destroy());
|
||||||
contextCategoryList.appendChild(new Element("li", {
|
|
||||||
html: '<a href="javascript:torrentNewCategoryFN();"><img src="images/list-add.svg" alt="QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]"/>QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]</a>'
|
const createMenuItem = (text, imgURL, clickFn) => {
|
||||||
}));
|
const anchor = document.createElement("a");
|
||||||
contextCategoryList.appendChild(new Element("li", {
|
anchor.textContent = text;
|
||||||
html: '<a href="javascript:torrentSetCategoryFN(0);"><img src="images/edit-clear.svg" alt="QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]"/>QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]</a>'
|
anchor.addEventListener("click", clickFn);
|
||||||
}));
|
|
||||||
|
const img = document.createElement("img");
|
||||||
|
img.src = imgURL;
|
||||||
|
img.alt = text;
|
||||||
|
anchor.prepend(img);
|
||||||
|
|
||||||
|
const item = document.createElement("li");
|
||||||
|
item.appendChild(anchor);
|
||||||
|
|
||||||
|
return item;
|
||||||
|
};
|
||||||
|
contextCategoryList.appendChild(createMenuItem("QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]", "images/list-add.svg", torrentNewCategoryFN));
|
||||||
|
contextCategoryList.appendChild(createMenuItem("QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]", "images/edit-clear.svg", () => { torrentSetCategoryFN(0); }));
|
||||||
|
|
||||||
const sortedCategories = [];
|
const sortedCategories = [];
|
||||||
categoryList.forEach((category, hash) => sortedCategories.push({
|
categoryList.forEach((category, hash) => sortedCategories.push({
|
||||||
|
@ -465,14 +477,25 @@ window.qBittorrent.ContextMenu ??= (() => {
|
||||||
|
|
||||||
let first = true;
|
let first = true;
|
||||||
for (const { categoryName, categoryHash } of sortedCategories) {
|
for (const { categoryName, categoryHash } of sortedCategories) {
|
||||||
const el = new Element("li", {
|
const anchor = document.createElement("a");
|
||||||
html: `<a href="javascript:torrentSetCategoryFN(${categoryHash});"><img src="images/view-categories.svg"/>${window.qBittorrent.Misc.escapeHtml(categoryName)}</a>`
|
anchor.href = `#Category/${categoryName}`;
|
||||||
|
anchor.textContent = categoryName;
|
||||||
|
anchor.addEventListener("click", (event) => {
|
||||||
|
torrentSetCategoryFN(categoryHash);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const img = document.createElement("img");
|
||||||
|
img.src = "images/view-categories.svg";
|
||||||
|
anchor.prepend(img);
|
||||||
|
|
||||||
|
const setCategoryItem = document.createElement("li");
|
||||||
|
setCategoryItem.appendChild(anchor);
|
||||||
if (first) {
|
if (first) {
|
||||||
el.addClass("separator");
|
setCategoryItem.addClass("separator");
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
contextCategoryList.appendChild(el);
|
|
||||||
|
contextCategoryList.appendChild(setCategoryItem);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -481,18 +504,23 @@ window.qBittorrent.ContextMenu ??= (() => {
|
||||||
while (contextTagList.firstChild !== null)
|
while (contextTagList.firstChild !== null)
|
||||||
contextTagList.removeChild(contextTagList.firstChild);
|
contextTagList.removeChild(contextTagList.firstChild);
|
||||||
|
|
||||||
contextTagList.appendChild(new Element("li", {
|
const createMenuItem = (text, imgURL, clickFn) => {
|
||||||
html: '<a href="javascript:torrentAddTagsFN();">'
|
const anchor = document.createElement("a");
|
||||||
+ '<img src="images/list-add.svg" alt="QBT_TR(Add...)QBT_TR[CONTEXT=TransferListWidget]"/>'
|
anchor.textContent = text;
|
||||||
+ " QBT_TR(Add...)QBT_TR[CONTEXT=TransferListWidget]"
|
anchor.addEventListener("click", clickFn);
|
||||||
+ "</a>"
|
|
||||||
}));
|
const img = document.createElement("img");
|
||||||
contextTagList.appendChild(new Element("li", {
|
img.src = imgURL;
|
||||||
html: '<a href="javascript:torrentRemoveAllTagsFN();">'
|
img.alt = text;
|
||||||
+ '<img src="images/edit-clear.svg" alt="QBT_TR(Remove All)QBT_TR[CONTEXT=TransferListWidget]"/>'
|
anchor.prepend(img);
|
||||||
+ " QBT_TR(Remove All)QBT_TR[CONTEXT=TransferListWidget]"
|
|
||||||
+ "</a>"
|
const item = document.createElement("li");
|
||||||
}));
|
item.appendChild(anchor);
|
||||||
|
|
||||||
|
return item;
|
||||||
|
};
|
||||||
|
contextTagList.appendChild(createMenuItem("QBT_TR(Add...)QBT_TR[CONTEXT=TransferListWidget]", "images/list-add.svg", torrentAddTagsFN));
|
||||||
|
contextTagList.appendChild(createMenuItem("QBT_TR(Remove All)QBT_TR[CONTEXT=TransferListWidget]", "images/edit-clear.svg", torrentRemoveAllTagsFN));
|
||||||
|
|
||||||
const sortedTags = [];
|
const sortedTags = [];
|
||||||
tagList.forEach((tag, hash) => sortedTags.push({
|
tagList.forEach((tag, hash) => sortedTags.push({
|
||||||
|
@ -503,14 +531,28 @@ window.qBittorrent.ContextMenu ??= (() => {
|
||||||
|
|
||||||
for (let i = 0; i < sortedTags.length; ++i) {
|
for (let i = 0; i < sortedTags.length; ++i) {
|
||||||
const { tagName, tagHash } = sortedTags[i];
|
const { tagName, tagHash } = sortedTags[i];
|
||||||
const el = new Element("li", {
|
|
||||||
html: `<a href="#Tag/${tagHash}" onclick="event.preventDefault(); torrentSetTagsFN(${tagHash}, !event.currentTarget.getElement('input[type=checkbox]').checked);">`
|
const input = document.createElement("input");
|
||||||
+ '<input type="checkbox" onclick="this.checked = !this.checked;"> ' + window.qBittorrent.Misc.escapeHtml(tagName)
|
input.type = "checkbox";
|
||||||
+ "</a>"
|
input.addEventListener("click", (event) => {
|
||||||
|
input.checked = !input.checked;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const anchor = document.createElement("a");
|
||||||
|
anchor.href = `#Tag/${tagName}`;
|
||||||
|
anchor.textContent = tagName;
|
||||||
|
anchor.addEventListener("click", (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
torrentSetTagsFN(tagHash, !input.checked);
|
||||||
|
});
|
||||||
|
anchor.prepend(input);
|
||||||
|
|
||||||
|
const setTagItem = document.createElement("li");
|
||||||
|
setTagItem.appendChild(anchor);
|
||||||
if (i === 0)
|
if (i === 0)
|
||||||
el.addClass("separator");
|
setTagItem.addClass("separator");
|
||||||
contextTagList.appendChild(el);
|
|
||||||
|
contextTagList.appendChild(setTagItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -333,10 +333,18 @@ window.qBittorrent.DynamicTable ??= (() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const createLi = function(columnName, text) {
|
const createLi = function(columnName, text) {
|
||||||
const html = '<a href="#' + columnName + '" ><img src="images/checked-completed.svg"/>' + window.qBittorrent.Misc.escapeHtml(text) + "</a>";
|
const anchor = document.createElement("a");
|
||||||
return new Element("li", {
|
anchor.href = `#${columnName}`;
|
||||||
html: html
|
anchor.textContent = text;
|
||||||
});
|
|
||||||
|
const img = document.createElement("img");
|
||||||
|
img.src = "images/checked-completed.svg";
|
||||||
|
anchor.prepend(img);
|
||||||
|
|
||||||
|
const listItem = document.createElement("li");
|
||||||
|
listItem.appendChild(anchor);
|
||||||
|
|
||||||
|
return listItem;
|
||||||
};
|
};
|
||||||
|
|
||||||
const actions = {};
|
const actions = {};
|
||||||
|
@ -2095,8 +2103,7 @@ window.qBittorrent.DynamicTable ??= (() => {
|
||||||
},
|
},
|
||||||
id: dirImgId
|
id: dirImgId
|
||||||
});
|
});
|
||||||
const html = dirImg.outerHTML + span.outerHTML;
|
td.replaceChildren(dirImg, span);
|
||||||
td.innerHTML = html;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // is file
|
else { // is file
|
||||||
|
@ -2108,7 +2115,7 @@ window.qBittorrent.DynamicTable ??= (() => {
|
||||||
"margin-left": ((node.depth + 1) * 20)
|
"margin-left": ((node.depth + 1) * 20)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
td.innerHTML = span.outerHTML;
|
td.replaceChildren(span);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2122,7 +2129,7 @@ window.qBittorrent.DynamicTable ??= (() => {
|
||||||
text: value,
|
text: value,
|
||||||
id: fileNameRenamedId,
|
id: fileNameRenamedId,
|
||||||
});
|
});
|
||||||
td.innerHTML = span.outerHTML;
|
td.replaceChildren(span);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -2428,8 +2435,7 @@ window.qBittorrent.DynamicTable ??= (() => {
|
||||||
},
|
},
|
||||||
id: dirImgId
|
id: dirImgId
|
||||||
});
|
});
|
||||||
const html = collapseIcon.outerHTML + dirImg.outerHTML + span.outerHTML;
|
td.replaceChildren(collapseIcon, dirImg, span);
|
||||||
td.innerHTML = html;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -2441,7 +2447,7 @@ window.qBittorrent.DynamicTable ??= (() => {
|
||||||
"margin-left": ((node.depth + 1) * 20)
|
"margin-left": ((node.depth + 1) * 20)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
td.innerHTML = span.outerHTML;
|
td.replaceChildren(span);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -165,32 +165,31 @@ window.qBittorrent.PropFiles ??= (() => {
|
||||||
return ($("comboPrio" + id) !== null);
|
return ($("comboPrio" + id) !== null);
|
||||||
};
|
};
|
||||||
|
|
||||||
const createPriorityOptionElement = function(priority, selected, html) {
|
const createPriorityCombo = (id, fileId, selectedPriority) => {
|
||||||
const elem = new Element("option");
|
const createOption = (priority, isSelected, text) => {
|
||||||
elem.value = priority.toString();
|
const option = document.createElement("option");
|
||||||
elem.innerHTML = html;
|
option.value = priority.toString();
|
||||||
if (selected)
|
option.selected = isSelected;
|
||||||
elem.selected = true;
|
option.textContent = text;
|
||||||
return elem;
|
return option;
|
||||||
};
|
};
|
||||||
|
|
||||||
const createPriorityCombo = function(id, fileId, selectedPriority) {
|
const select = document.createElement("select");
|
||||||
const select = new Element("select");
|
|
||||||
select.id = "comboPrio" + id;
|
select.id = "comboPrio" + id;
|
||||||
select.setAttribute("data-id", id);
|
select.setAttribute("data-id", id);
|
||||||
select.setAttribute("data-file-id", fileId);
|
select.setAttribute("data-file-id", fileId);
|
||||||
select.addClass("combo_priority");
|
select.addClass("combo_priority");
|
||||||
select.addEventListener("change", fileComboboxChanged);
|
select.addEventListener("change", fileComboboxChanged);
|
||||||
|
|
||||||
createPriorityOptionElement(FilePriority.Ignored, (FilePriority.Ignored === selectedPriority), "QBT_TR(Do not download)QBT_TR[CONTEXT=PropListDelegate]").injectInside(select);
|
select.appendChild(createOption(FilePriority.Ignored, (FilePriority.Ignored === selectedPriority), "QBT_TR(Do not download)QBT_TR[CONTEXT=PropListDelegate]"));
|
||||||
createPriorityOptionElement(FilePriority.Normal, (FilePriority.Normal === selectedPriority), "QBT_TR(Normal)QBT_TR[CONTEXT=PropListDelegate]").injectInside(select);
|
select.appendChild(createOption(FilePriority.Normal, (FilePriority.Normal === selectedPriority), "QBT_TR(Normal)QBT_TR[CONTEXT=PropListDelegate]"));
|
||||||
createPriorityOptionElement(FilePriority.High, (FilePriority.High === selectedPriority), "QBT_TR(High)QBT_TR[CONTEXT=PropListDelegate]").injectInside(select);
|
select.appendChild(createOption(FilePriority.High, (FilePriority.High === selectedPriority), "QBT_TR(High)QBT_TR[CONTEXT=PropListDelegate]"));
|
||||||
createPriorityOptionElement(FilePriority.Maximum, (FilePriority.Maximum === selectedPriority), "QBT_TR(Maximum)QBT_TR[CONTEXT=PropListDelegate]").injectInside(select);
|
select.appendChild(createOption(FilePriority.Maximum, (FilePriority.Maximum === selectedPriority), "QBT_TR(Maximum)QBT_TR[CONTEXT=PropListDelegate]"));
|
||||||
|
|
||||||
// "Mixed" priority is for display only; it shouldn't be selectable
|
// "Mixed" priority is for display only; it shouldn't be selectable
|
||||||
const mixedPriorityOption = createPriorityOptionElement(FilePriority.Mixed, (FilePriority.Mixed === selectedPriority), "QBT_TR(Mixed)QBT_TR[CONTEXT=PropListDelegate]");
|
const mixedPriorityOption = createOption(FilePriority.Mixed, (FilePriority.Mixed === selectedPriority), "QBT_TR(Mixed)QBT_TR[CONTEXT=PropListDelegate]");
|
||||||
mixedPriorityOption.disabled = true;
|
mixedPriorityOption.disabled = true;
|
||||||
mixedPriorityOption.injectInside(select);
|
select.appendChild(mixedPriorityOption);
|
||||||
|
|
||||||
return select;
|
return select;
|
||||||
};
|
};
|
||||||
|
|
|
@ -67,7 +67,7 @@ window.qBittorrent.PropGeneral ??= (() => {
|
||||||
$("torrent_hash_v1").textContent = "";
|
$("torrent_hash_v1").textContent = "";
|
||||||
$("torrent_hash_v2").textContent = "";
|
$("torrent_hash_v2").textContent = "";
|
||||||
$("save_path").textContent = "";
|
$("save_path").textContent = "";
|
||||||
$("comment").innerHTML = "";
|
$("comment").textContent = "";
|
||||||
$("private").textContent = "";
|
$("private").textContent = "";
|
||||||
piecesBar.clear();
|
piecesBar.clear();
|
||||||
};
|
};
|
||||||
|
|
|
@ -63,7 +63,7 @@ window.qBittorrent.PropWebseeds ??= (() => {
|
||||||
updateRow: function(tr, row) {
|
updateRow: function(tr, row) {
|
||||||
const tds = tr.getElements("td");
|
const tds = tr.getElements("td");
|
||||||
for (let i = 0; i < row.length; ++i)
|
for (let i = 0; i < row.length; ++i)
|
||||||
tds[i].innerHTML = row[i];
|
tds[i].textContent = row[i];
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -78,9 +78,9 @@ window.qBittorrent.PropWebseeds ??= (() => {
|
||||||
const tr = new Element("tr");
|
const tr = new Element("tr");
|
||||||
this.rows.set(url, tr);
|
this.rows.set(url, tr);
|
||||||
for (let i = 0; i < row.length; ++i) {
|
for (let i = 0; i < row.length; ++i) {
|
||||||
const td = new Element("td");
|
const td = document.createElement("td");
|
||||||
td.innerHTML = row[i];
|
td.textContent = row[i];
|
||||||
td.injectInside(tr);
|
tr.appendChild(td);
|
||||||
}
|
}
|
||||||
tr.injectInside(this.table);
|
tr.injectInside(this.table);
|
||||||
},
|
},
|
||||||
|
|
|
@ -174,16 +174,15 @@ window.qBittorrent.Search ??= (() => {
|
||||||
|
|
||||||
tabElem.appendChild(getStatusIconElement("QBT_TR(Searching...)QBT_TR[CONTEXT=SearchJobWidget]", "images/queued.svg"));
|
tabElem.appendChild(getStatusIconElement("QBT_TR(Searching...)QBT_TR[CONTEXT=SearchJobWidget]", "images/queued.svg"));
|
||||||
|
|
||||||
const liElement = new Element("li", {
|
const listItem = document.createElement("li");
|
||||||
id: newTabId,
|
listItem.id = newTabId;
|
||||||
class: "selected",
|
listItem.classList.add("selected");
|
||||||
html: tabElem.outerHTML,
|
listItem.addEventListener("click", (e) => {
|
||||||
});
|
setActiveTab(listItem);
|
||||||
liElement.addEventListener("click", (e) => {
|
|
||||||
setActiveTab(liElement);
|
|
||||||
$("startSearchButton").textContent = "QBT_TR(Search)QBT_TR[CONTEXT=SearchEngineWidget]";
|
$("startSearchButton").textContent = "QBT_TR(Search)QBT_TR[CONTEXT=SearchEngineWidget]";
|
||||||
});
|
});
|
||||||
$("searchTabs").appendChild(liElement);
|
listItem.appendChild(tabElem);
|
||||||
|
$("searchTabs").appendChild(listItem);
|
||||||
|
|
||||||
// unhide the results elements
|
// unhide the results elements
|
||||||
if (numSearchTabs() >= 1) {
|
if (numSearchTabs() >= 1) {
|
||||||
|
@ -194,7 +193,7 @@ window.qBittorrent.Search ??= (() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// select new tab
|
// select new tab
|
||||||
setActiveTab(liElement);
|
setActiveTab(listItem);
|
||||||
|
|
||||||
searchResultsTable.clear();
|
searchResultsTable.clear();
|
||||||
resetFilters();
|
resetFilters();
|
||||||
|
@ -577,26 +576,27 @@ window.qBittorrent.Search ??= (() => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getSearchCategories = function() {
|
const getSearchCategories = () => {
|
||||||
const populateCategorySelect = function(categories) {
|
const populateCategorySelect = (categories) => {
|
||||||
const categoryHtml = [];
|
const categoryOptions = [];
|
||||||
categories.each((category) => {
|
|
||||||
const option = new Element("option");
|
for (const category of categories) {
|
||||||
|
const option = document.createElement("option");
|
||||||
option.value = category.id;
|
option.value = category.id;
|
||||||
option.textContent = category.name;
|
option.textContent = category.name;
|
||||||
categoryHtml.push(option.outerHTML);
|
categoryOptions.push(option);
|
||||||
});
|
};
|
||||||
|
|
||||||
// first category is "All Categories"
|
// first category is "All Categories"
|
||||||
if (categoryHtml.length > 1) {
|
if (categoryOptions.length > 1) {
|
||||||
// add separator
|
// add separator
|
||||||
const option = new Element("option");
|
const option = document.createElement("option");
|
||||||
option.disabled = true;
|
option.disabled = true;
|
||||||
option.textContent = "──────────";
|
option.textContent = "──────────";
|
||||||
categoryHtml.splice(1, 0, option.outerHTML);
|
categoryOptions.splice(1, 0, option);
|
||||||
}
|
}
|
||||||
|
|
||||||
$("categorySelect").innerHTML = categoryHtml.join("");
|
$("categorySelect").replaceChildren(...categoryOptions);
|
||||||
};
|
};
|
||||||
|
|
||||||
const selectedPlugin = $("pluginsSelect").value;
|
const selectedPlugin = $("pluginsSelect").value;
|
||||||
|
@ -629,7 +629,16 @@ window.qBittorrent.Search ??= (() => {
|
||||||
url: new URI("api/v2/search/plugins"),
|
url: new URI("api/v2/search/plugins"),
|
||||||
method: "get",
|
method: "get",
|
||||||
noCache: true,
|
noCache: true,
|
||||||
onSuccess: function(response) {
|
onSuccess: (response) => {
|
||||||
|
const createOption = (text, value, disabled = false) => {
|
||||||
|
const option = document.createElement("option");
|
||||||
|
if (value !== undefined)
|
||||||
|
option.value = value;
|
||||||
|
option.textContent = text;
|
||||||
|
option.disabled = disabled;
|
||||||
|
return option;
|
||||||
|
};
|
||||||
|
|
||||||
if (response !== prevSearchPluginsResponse) {
|
if (response !== prevSearchPluginsResponse) {
|
||||||
prevSearchPluginsResponse = response;
|
prevSearchPluginsResponse = response;
|
||||||
searchPlugins.length = 0;
|
searchPlugins.length = 0;
|
||||||
|
@ -637,9 +646,9 @@ window.qBittorrent.Search ??= (() => {
|
||||||
searchPlugins.push(plugin);
|
searchPlugins.push(plugin);
|
||||||
});
|
});
|
||||||
|
|
||||||
const pluginsHtml = [];
|
const pluginOptions = [];
|
||||||
pluginsHtml.push('<option value="enabled">QBT_TR(Only enabled)QBT_TR[CONTEXT=SearchEngineWidget]</option>');
|
pluginOptions.push(createOption("QBT_TR(Only enabled)QBT_TR[CONTEXT=SearchEngineWidget]", "enabled"));
|
||||||
pluginsHtml.push('<option value="all">QBT_TR(All plugins)QBT_TR[CONTEXT=SearchEngineWidget]</option>');
|
pluginOptions.push(createOption("QBT_TR(All plugins)QBT_TR[CONTEXT=SearchEngineWidget]", "all"));
|
||||||
|
|
||||||
const searchPluginsEmpty = (searchPlugins.length === 0);
|
const searchPluginsEmpty = (searchPlugins.length === 0);
|
||||||
if (!searchPluginsEmpty) {
|
if (!searchPluginsEmpty) {
|
||||||
|
@ -656,14 +665,14 @@ window.qBittorrent.Search ??= (() => {
|
||||||
|
|
||||||
allPlugins.each((plugin) => {
|
allPlugins.each((plugin) => {
|
||||||
if (plugin.enabled === true)
|
if (plugin.enabled === true)
|
||||||
pluginsHtml.push("<option value='" + window.qBittorrent.Misc.escapeHtml(plugin.name) + "'>" + window.qBittorrent.Misc.escapeHtml(plugin.fullName) + "</option>");
|
pluginOptions.push(createOption(plugin.fullName, plugin.name));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (pluginsHtml.length > 2)
|
if (pluginOptions.length > 2)
|
||||||
pluginsHtml.splice(2, 0, "<option disabled>──────────</option>");
|
pluginOptions.splice(2, 0, createOption("──────────", undefined, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
$("pluginsSelect").innerHTML = pluginsHtml.join("");
|
$("pluginsSelect").replaceChildren(...pluginOptions);
|
||||||
|
|
||||||
$("searchPattern").disabled = searchPluginsEmpty;
|
$("searchPattern").disabled = searchPluginsEmpty;
|
||||||
$("categorySelect").disabled = searchPluginsEmpty;
|
$("categorySelect").disabled = searchPluginsEmpty;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue