WebUI: Use vanilla JS to create elements

All elements are now created using createElement() method:
https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement

PR #21975.

---------

Co-authored-by: Chocobo1 <Chocobo1@users.noreply.github.com>
This commit is contained in:
skomerko 2024-12-14 20:31:44 +01:00 committed by GitHub
parent 4c6dd8e68d
commit 14684c8c83
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 167 additions and 190 deletions

View file

@ -46,7 +46,7 @@
// Inject checkbox into the first column of the table header
const tableHeaders = $$("#bulkRenameFilesTableFixedHeaderDiv .dynamicTableHeader th");
if (tableHeaders.length > 0) {
const checkboxHeader = new Element("input");
const checkboxHeader = document.createElement("input");
checkboxHeader.type = "checkbox";
checkboxHeader.id = "rootMultiRename_cb";
checkboxHeader.addEventListener("click", (e) => {
@ -56,7 +56,7 @@
});
const checkboxTH = tableHeaders[0];
checkboxHeader.injectInside(checkboxTH);
checkboxTH.append(checkboxHeader);
}
// Register keyboard events to modal window

View file

@ -48,7 +48,7 @@ window.qBittorrent.Download ??= (() => {
continue;
const category = data[i];
const option = new Element("option");
const option = document.createElement("option");
option.value = category.name;
option.textContent = category.name;
$("categorySelect").appendChild(option);

View file

@ -433,10 +433,12 @@ window.qBittorrent.DynamicTable ??= (() => {
const menuId = this.dynamicTableDivId + "_headerMenu";
// reuse menu if already exists
const ul = $(menuId) ?? new Element("ul", {
id: menuId,
class: "contextMenu scrollableMenu"
});
let ul = document.getElementById(menuId);
if (ul === null) {
ul = document.createElement("ul");
ul.id = menuId;
ul.className = "contextMenu scrollableMenu";
}
const createLi = (columnName, text) => {
const anchor = document.createElement("a");
@ -499,7 +501,7 @@ window.qBittorrent.DynamicTable ??= (() => {
ul.firstElementChild.classList.add("separator");
ul.insertBefore(autoResizeAllElement, ul.firstElementChild);
ul.insertBefore(autoResizeElement, ul.firstElementChild);
ul.inject(document.body);
document.body.append(ul);
this.headerContextMenu = new DynamicTableHeaderContextMenuClass({
targets: "#" + this.dynamicTableFixedHeaderDivId + " tr th",
@ -549,8 +551,8 @@ window.qBittorrent.DynamicTable ??= (() => {
this.columns.push(column);
this.columns[name] = column;
this.hiddenTableHeader.appendChild(new Element("th"));
this.fixedTableHeader.appendChild(new Element("th"));
this.hiddenTableHeader.append(document.createElement("th"));
this.fixedTableHeader.append(document.createElement("th"));
},
loadColumnsOrder: function() {
@ -850,7 +852,7 @@ window.qBittorrent.DynamicTable ??= (() => {
this.updateRow(trs[rowPos], fullUpdate);
}
else { // else create a new row in the table
const tr = new Element("tr");
const tr = document.createElement("tr");
// set tabindex so element receives keydown events
// more info: https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event
tr.tabIndex = -1;
@ -860,10 +862,10 @@ window.qBittorrent.DynamicTable ??= (() => {
tr["rowId"] = rowId;
for (let k = 0; k < this.columns.length; ++k) {
const td = new Element("td");
const td = document.createElement("td");
if ((this.columns[k].visible === "0") || this.columns[k].force_hide)
td.classList.add("invisible");
td.injectInside(tr);
tr.append(td);
}
// Insert
@ -1104,11 +1106,11 @@ window.qBittorrent.DynamicTable ??= (() => {
}
}
else {
td.adopt(new Element("img", {
"src": img_path,
"class": "stateIcon",
"title": state
}));
const img = document.createElement("img");
img.src = img_path;
img.className = "stateIcon";
img.title = state;
td.append(img);
}
};
@ -1237,7 +1239,7 @@ window.qBittorrent.DynamicTable ??= (() => {
else {
if (ProgressColumnWidth < 0)
ProgressColumnWidth = td.offsetWidth;
td.adopt(new window.qBittorrent.ProgressBar.ProgressBar(progressFormatted.toFloat(), {
td.append(new window.qBittorrent.ProgressBar.ProgressBar(progressFormatted.toFloat(), {
"width": ProgressColumnWidth - 5
}));
td.resized = false;
@ -2213,13 +2215,11 @@ window.qBittorrent.DynamicTable ??= (() => {
const id = row.rowId;
const value = this.getRowValue(row);
const treeImg = new Element("img", {
src: "images/L.gif",
styles: {
"margin-bottom": -2
}
});
const checkbox = new Element("input");
const treeImg = document.createElement("img");
treeImg.src = "images/L.gif";
treeImg.style.marginBottom = "-2px";
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.id = "cbRename" + id;
checkbox.setAttribute("data-id", id);
@ -2235,7 +2235,7 @@ window.qBittorrent.DynamicTable ??= (() => {
checkbox.checked = (value === 0);
checkbox.state = checkbox.checked ? "checked" : "unchecked";
checkbox.indeterminate = false;
td.adopt(treeImg, checkbox);
td.replaceChildren(treeImg, checkbox);
};
this.columns["checked"].staticWidth = 50;
@ -2253,32 +2253,26 @@ window.qBittorrent.DynamicTable ??= (() => {
$(fileNameId).textContent = value;
}
else {
const span = new Element("span", {
text: value,
id: fileNameId
});
const dirImg = new Element("img", {
src: "images/directory.svg",
styles: {
"width": 20,
"padding-right": 5,
"margin-bottom": -3,
"margin-left": (node.depth * 20)
},
id: dirImgId
});
const span = document.createElement("span");
span.textContent = value;
span.id = fileNameId;
const dirImg = document.createElement("img");
dirImg.src = "images/directory.svg";
dirImg.style.width = "20px";
dirImg.style.paddingRight = "5px";
dirImg.style.marginBottom = "-3px";
dirImg.style.marginLeft = `${node.depth * 20}px`;
dirImg.id = dirImgId;
td.replaceChildren(dirImg, span);
}
}
else { // is file
const value = this.getRowValue(row);
const span = new Element("span", {
text: value,
id: fileNameId,
styles: {
"margin-left": ((node.depth + 1) * 20)
}
});
const span = document.createElement("span");
span.textContent = value;
span.id = fileNameId;
span.style.marginLeft = `${(node.depth + 1) * 20}px`;
td.replaceChildren(span);
}
};
@ -2289,10 +2283,9 @@ window.qBittorrent.DynamicTable ??= (() => {
const fileNameRenamedId = "filesTablefileRenamed" + id;
const value = this.getRowValue(row);
const span = new Element("span", {
text: value,
id: fileNameRenamedId,
});
const span = document.createElement("span");
span.textContent = value;
span.id = fileNameRenamedId;
td.replaceChildren(span);
};
},
@ -2540,13 +2533,10 @@ window.qBittorrent.DynamicTable ??= (() => {
window.qBittorrent.PropFiles.updateDownloadCheckbox(id, value);
}
else {
const treeImg = new Element("img", {
src: "images/L.gif",
styles: {
"margin-bottom": -2
}
});
td.adopt(treeImg, window.qBittorrent.PropFiles.createDownloadCheckbox(id, row.full_data.fileId, value));
const treeImg = document.createElement("img");
treeImg.src = "images/L.gif";
treeImg.style.marginBottom = "-2px";
td.append(treeImg, window.qBittorrent.PropFiles.createDownloadCheckbox(id, row.full_data.fileId, value));
}
};
this.columns["checked"].staticWidth = 50;
@ -2566,41 +2556,34 @@ window.qBittorrent.DynamicTable ??= (() => {
$(fileNameId).textContent = value;
}
else {
const collapseIcon = new Element("img", {
src: "images/go-down.svg",
styles: {
"margin-left": (node.depth * 20)
},
class: "filesTableCollapseIcon",
id: collapseIconId,
"data-id": id,
onclick: "qBittorrent.PropFiles.collapseIconClicked(this)"
});
const span = new Element("span", {
text: value,
id: fileNameId
});
const dirImg = new Element("img", {
src: "images/directory.svg",
styles: {
"width": 20,
"padding-right": 5,
"margin-bottom": -3
},
id: dirImgId
});
const collapseIcon = document.createElement("img");
collapseIcon.src = "images/go-down.svg";
collapseIcon.style.marginLeft = `${node.depth * 20}px`;
collapseIcon.className = "filesTableCollapseIcon";
collapseIcon.id = collapseIconId;
collapseIcon.setAttribute("data-id", id);
collapseIcon.addEventListener("click", function(e) { qBittorrent.PropFiles.collapseIconClicked(this); });
const span = document.createElement("span");
span.textContent = value;
span.id = fileNameId;
const dirImg = document.createElement("img");
dirImg.src = "images/directory.svg";
dirImg.style.width = "20px";
dirImg.style.paddingRight = "5px";
dirImg.style.marginBottom = "-3px";
dirImg.id = dirImgId;
td.replaceChildren(collapseIcon, dirImg, span);
}
}
else {
const value = this.getRowValue(row);
const span = new Element("span", {
text: value,
id: fileNameId,
styles: {
"margin-left": ((node.depth + 1) * 20)
}
});
const span = document.createElement("span");
span.textContent = value;
span.id = fileNameId;
span.style.marginLeft = `${(node.depth + 1) * 20}px`;
td.replaceChildren(span);
}
};
@ -2621,7 +2604,7 @@ window.qBittorrent.DynamicTable ??= (() => {
const progressBar = $("pbf_" + id);
if (progressBar === null) {
td.adopt(new window.qBittorrent.ProgressBar.ProgressBar(value.toFloat(), {
td.append(new window.qBittorrent.ProgressBar.ProgressBar(value.toFloat(), {
id: "pbf_" + id,
width: 80
}));
@ -2640,7 +2623,7 @@ window.qBittorrent.DynamicTable ??= (() => {
if (window.qBittorrent.PropFiles.isPriorityComboExists(id))
window.qBittorrent.PropFiles.updatePriorityCombo(id, value);
else
td.adopt(window.qBittorrent.PropFiles.createPriorityCombo(id, row.full_data.fileId, value));
td.append(window.qBittorrent.PropFiles.createPriorityCombo(id, row.full_data.fileId, value));
};
this.columns["priority"].staticWidth = 140;
@ -2887,12 +2870,12 @@ window.qBittorrent.DynamicTable ??= (() => {
}
}
else {
td.adopt(new Element("img", {
"src": img_path,
"class": "stateIcon",
"height": "22px",
"width": "22px"
}));
const img = document.createElement("img");
img.src = img_path;
img.className = "stateIcon";
img.width = "22";
img.height = "22";
td.append(img);
}
};
},
@ -2929,8 +2912,8 @@ window.qBittorrent.DynamicTable ??= (() => {
this.columns.push(column);
this.columns[name] = column;
this.hiddenTableHeader.appendChild(new Element("th"));
this.fixedTableHeader.appendChild(new Element("th"));
this.hiddenTableHeader.append(document.createElement("th"));
this.fixedTableHeader.append(document.createElement("th"));
}
});
@ -3017,8 +3000,8 @@ window.qBittorrent.DynamicTable ??= (() => {
this.columns.push(column);
this.columns[name] = column;
this.hiddenTableHeader.appendChild(new Element("th"));
this.fixedTableHeader.appendChild(new Element("th"));
this.hiddenTableHeader.append(document.createElement("th"));
this.fixedTableHeader.append(document.createElement("th"));
}
});
@ -3030,7 +3013,7 @@ window.qBittorrent.DynamicTable ??= (() => {
this.columns["checked"].updateTd = function(td, row) {
if ($("cbRssDlRule" + row.rowId) === null) {
const checkbox = new Element("input");
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.id = "cbRssDlRule" + row.rowId;
checkbox.checked = row.full_data.checked;
@ -3101,8 +3084,8 @@ window.qBittorrent.DynamicTable ??= (() => {
this.columns.push(column);
this.columns[name] = column;
this.hiddenTableHeader.appendChild(new Element("th"));
this.fixedTableHeader.appendChild(new Element("th"));
this.hiddenTableHeader.append(document.createElement("th"));
this.fixedTableHeader.append(document.createElement("th"));
},
selectRow: function(rowId) {
this.selectedRows.push(rowId);
@ -3128,7 +3111,7 @@ window.qBittorrent.DynamicTable ??= (() => {
this.columns["checked"].updateTd = function(td, row) {
if ($("cbRssDlFeed" + row.rowId) === null) {
const checkbox = new Element("input");
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.id = "cbRssDlFeed" + row.rowId;
checkbox.checked = row.full_data.checked;
@ -3187,8 +3170,8 @@ window.qBittorrent.DynamicTable ??= (() => {
this.columns.push(column);
this.columns[name] = column;
this.hiddenTableHeader.appendChild(new Element("th"));
this.fixedTableHeader.appendChild(new Element("th"));
this.hiddenTableHeader.append(document.createElement("th"));
this.fixedTableHeader.append(document.createElement("th"));
},
selectRow: () => {}
});
@ -3236,8 +3219,8 @@ window.qBittorrent.DynamicTable ??= (() => {
this.columns.push(column);
this.columns[name] = column;
this.hiddenTableHeader.appendChild(new Element("th"));
this.fixedTableHeader.appendChild(new Element("th"));
this.hiddenTableHeader.append(document.createElement("th"));
this.fixedTableHeader.append(document.createElement("th"));
},
selectRow: () => {},
updateRow: function(tr, fullUpdate) {

View file

@ -61,23 +61,20 @@ window.qBittorrent.PiecesBar ??= (() => {
Object.append(vals, parameters);
vals.height = Math.max(vals.height, 12);
const obj = new Element("div", {
"id": vals.id,
"class": "piecesbarWrapper",
"styles": {
"border": vals.borderSize.toString() + "px solid " + vals.borderColor,
"height": vals.height.toString() + "px",
}
});
const obj = document.createElement("div");
obj.id = vals.id;
obj.className = "piecesbarWrapper";
obj.style.border = `${vals.borderSize}px solid ${vals.borderColor}`;
obj.style.height = `${vals.height}px`;
obj.vals = vals;
obj.vals.pieces = [pieces, []].pick();
obj.vals.canvas = new Element("canvas", {
"id": vals.id + "_canvas",
"class": "piecesbarCanvas",
"width": (vals.width - (2 * vals.borderSize)).toString(),
"height": "1" // will stretch vertically to take up the height of the parent
});
const canvas = document.createElement("canvas");
canvas.id = `${vals.id}_canvas`;
canvas.className = "piecesbarCanvas";
canvas.width = `${vals.width - (2 * vals.borderSize)}`;
canvas.height = "1"; // will stretch vertically to take up the height of the parent
obj.vals.canvas = canvas;
obj.appendChild(obj.vals.canvas);
obj.setPieces = setPieces;

View file

@ -53,52 +53,51 @@ window.qBittorrent.ProgressBar ??= (() => {
Object.append(vals, parameters);
if (vals.height < 12)
vals.height = 12;
const obj = new Element("div", {
"id": vals.id,
"class": "progressbar_wrapper",
"styles": {
"border": "1px solid var(--color-border-default)",
"box-sizing": "content-box",
"width": vals.width,
"height": vals.height,
"position": "relative",
"margin": "0 auto"
}
});
const obj = document.createElement("div");
obj.id = vals.id;
obj.className = "progressbar_wrapper";
obj.style.border = "1px solid var(--color-border-default)";
obj.style.boxSizing = "content-box";
obj.style.width = `${vals.width}px`;
obj.style.height = `${vals.height}px`;
obj.style.position = "relative";
obj.style.margin = "0 auto";
obj.vals = vals;
obj.vals.value = [value, 0].pick();
obj.vals.dark = new Element("div", {
"id": vals.id + "_dark",
"class": "progressbar_dark",
"styles": {
"width": vals.width,
"height": vals.height,
"background": vals.darkbg,
"box-sizing": "content-box",
"color": vals.darkfg,
"position": "absolute",
"text-align": "center",
"left": 0,
"top": 0,
"line-height": vals.height
}
});
obj.vals.light = new Element("div", {
"id": vals.id + "_light",
"class": "progressbar_light",
"styles": {
"width": vals.width,
"height": vals.height,
"background": vals.lightbg,
"box-sizing": "content-box",
"color": vals.lightfg,
"position": "absolute",
"text-align": "center",
"left": 0,
"top": 0,
"line-height": vals.height
}
});
const dark = document.createElement("div");
dark.id = `${vals.id}_dark`;
dark.className = "progressbar_dark";
dark.style.width = `${vals.width}px`;
dark.style.height = `${vals.height}px`;
dark.style.background = vals.darkbg;
dark.style.boxSizing = "content-box";
dark.style.color = vals.darkfg;
dark.style.position = "absolute";
dark.style.textAlign = "center";
dark.style.left = "0";
dark.style.top = "0";
dark.style.lineHeight = `${vals.height}px`;
obj.vals.dark = dark;
const light = document.createElement("div");
light.id = `${vals.id}_light`;
light.className = "progressbar_light";
light.style.width = `${vals.width}px`;
light.style.height = `${vals.height}px`;
light.style.background = vals.lightbg;
light.style.boxSizing = "content-box";
light.style.color = vals.lightfg;
light.style.position = "absolute";
light.style.textAlign = "center";
light.style.left = "0";
light.style.top = "0";
light.style.lineHeight = `${vals.height}px`;
obj.vals.light = light;
obj.appendChild(obj.vals.dark);
obj.appendChild(obj.vals.light);
obj.getValue = ProgressBar_getValue;

View file

@ -131,7 +131,7 @@ window.qBittorrent.PropFiles ??= (() => {
};
const createDownloadCheckbox = (id, fileId, checked) => {
const checkbox = new Element("input");
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.id = "cbPrio" + id;
checkbox.setAttribute("data-id", id);
@ -623,13 +623,13 @@ window.qBittorrent.PropFiles ??= (() => {
// inject checkbox into table header
const tableHeaders = $$("#torrentFilesTableFixedHeaderDiv .dynamicTableHeader th");
if (tableHeaders.length > 0) {
const checkbox = new Element("input");
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.id = "tristate_cb";
checkbox.addEventListener("click", switchCheckboxState);
const checkboxTH = tableHeaders[0];
checkbox.injectInside(checkboxTH);
checkboxTH.append(checkbox);
}
// default sort by name column

View file

@ -175,20 +175,18 @@ window.qBittorrent.Search ??= (() => {
const createSearchTab = (searchId, pattern) => {
const newTabId = `${searchTabIdPrefix}${searchId}`;
const tabElem = new Element("a", {
text: pattern,
});
const tabElem = document.createElement("a");
tabElem.textContent = pattern;
const closeTabElem = new Element("img", {
alt: "QBT_TR(Close tab)QBT_TR[CONTEXT=SearchWidget]",
title: "QBT_TR(Close tab)QBT_TR[CONTEXT=SearchWidget]",
src: "images/application-exit.svg",
width: "10",
height: "10",
onclick: "qBittorrent.Search.closeSearchTab(this);",
});
closeTabElem.inject(tabElem, "top");
const closeTabElem = document.createElement("img");
closeTabElem.alt = "QBT_TR(Close tab)QBT_TR[CONTEXT=SearchWidget]";
closeTabElem.title = "QBT_TR(Close tab)QBT_TR[CONTEXT=SearchWidget]";
closeTabElem.src = "images/application-exit.svg";
closeTabElem.width = "10";
closeTabElem.height = "10";
closeTabElem.addEventListener("click", function(e) { qBittorrent.Search.closeSearchTab(this); });
tabElem.prepend(closeTabElem);
tabElem.appendChild(getStatusIconElement("QBT_TR(Searching...)QBT_TR[CONTEXT=SearchJobWidget]", "images/queued.svg"));
const listItem = document.createElement("li");
@ -375,14 +373,14 @@ window.qBittorrent.Search ??= (() => {
};
const getStatusIconElement = (text, image) => {
return new Element("img", {
alt: text,
title: text,
src: image,
class: "statusIcon",
width: "12",
height: "12",
});
const statusIcon = document.createElement("img");
statusIcon.alt = text;
statusIcon.title = text;
statusIcon.src = image;
statusIcon.className = "statusIcon";
statusIcon.width = "12";
statusIcon.height = "12";
return statusIcon;
};
const updateStatusIconElement = (searchId, text, image) => {