WebUI: Use modern class syntax in context menu classes

Context menu classes are now created using vanilla JS syntax (minimal changes to reduce MooTools bits).

PR #21598.
This commit is contained in:
skomerko 2024-10-19 10:32:20 +02:00 committed by GitHub
commit 5a0914e333
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 107 additions and 131 deletions

View file

@ -46,31 +46,24 @@ window.qBittorrent.ContextMenu ??= (() => {
};
let lastShownContextMenu = null;
const ContextMenu = new Class({
// implements
Implements: [Options, Events],
// options
options: {
actions: {},
menu: "menu_id",
stopEvent: true,
targets: "body",
offsets: {
x: 0,
y: 0
},
onShow: () => {},
onHide: () => {},
onClick: () => {},
fadeSpeed: 200,
touchTimer: 600
},
// initialization
initialize: function(options) {
// set options
this.setOptions(options);
class ContextMenu {
constructor(options) {
this.options = {
actions: {},
menu: "menu_id",
stopEvent: true,
targets: "body",
offsets: {
x: 0,
y: 0
},
onShow: () => {},
onHide: () => {},
onClick: () => {},
fadeSpeed: 200,
touchTimer: 600,
...options
};
// option diffs menu
this.menu = $(this.options.menu);
@ -92,9 +85,9 @@ window.qBittorrent.ContextMenu ??= (() => {
this.menu.style.position = "absolute";
this.menu.style.top = "-900000px";
this.menu.style.display = "block";
},
}
adjustMenuPosition: function(e) {
adjustMenuPosition(e) {
this.updateMenuItems();
const scrollableMenuMaxHeight = document.documentElement.clientHeight * 0.75;
@ -144,9 +137,9 @@ window.qBittorrent.ContextMenu ??= (() => {
ul.style.marginLeft = `${xPos - xPosOrigin}px`;
ul.style.marginTop = `${yPos - yPosOrigin}px`;
}
},
}
setupEventListeners: function(elem) {
setupEventListeners(elem) {
elem.addEventListener("contextmenu", (e) => {
this.triggerMenu(e, elem);
});
@ -171,21 +164,21 @@ window.qBittorrent.ContextMenu ??= (() => {
if (((now - touchStartAt) >= this.options.touchTimer) && isTargetUnchanged)
this.triggerMenu(touchStartEvent, elem);
}, { passive: true });
},
}
addTarget: function(t) {
addTarget(t) {
// prevent long press from selecting this text
t.style.userSelect = "none";
this.targets[this.targets.length] = t;
this.setupEventListeners(t);
},
}
searchAndAddTargets: function() {
searchAndAddTargets() {
document.querySelectorAll(this.options.targets).forEach((target) => { this.addTarget(target); });
},
}
triggerMenu: function(e, el) {
triggerMenu(e, el) {
if (this.options.disabled)
return;
@ -199,10 +192,10 @@ window.qBittorrent.ContextMenu ??= (() => {
this.adjustMenuPosition(e);
// show the menu
this.show();
},
}
// get things started
startListener: function() {
startListener() {
/* all elements */
this.targets.each((el) => {
this.setupEventListeners(el);
@ -218,7 +211,7 @@ window.qBittorrent.ContextMenu ??= (() => {
if (!menuItem.classList.contains("disabled")) {
const anchor = menuItem.firstElementChild;
this.execute(anchor.href.split("#")[1], this.options.element);
this.fireEvent("click", [anchor, e]);
this.options.onClick.call(this, anchor, e);
}
else {
e.stopPropagation();
@ -229,107 +222,103 @@ window.qBittorrent.ContextMenu ??= (() => {
$(document.body).addEventListener("click", () => {
this.hide();
});
},
}
updateMenuItems: function() {},
updateMenuItems() {}
// show menu
show: function(trigger) {
show(trigger) {
if (lastShownContextMenu && (lastShownContextMenu !== this))
lastShownContextMenu.hide();
this.fx.start(1);
this.fireEvent("show");
this.options.onShow.call(this);
lastShownContextMenu = this;
return this;
},
}
// hide the menu
hide: function(trigger) {
hide(trigger) {
if (lastShownContextMenu && (lastShownContextMenu.menu.style.visibility !== "hidden")) {
this.fx.start(0);
// this.menu.fade('out');
this.fireEvent("hide");
this.options.onHide.call(this);
}
return this;
},
}
setItemChecked: function(item, checked) {
setItemChecked(item, checked) {
this.menu.getElement("a[href$=" + item + "]").firstChild.style.opacity =
checked ? "1" : "0";
return this;
},
}
getItemChecked: function(item) {
getItemChecked(item) {
return this.menu.getElement("a[href$=" + item + "]").firstChild.style.opacity !== "0";
},
}
// hide an item
hideItem: function(item) {
hideItem(item) {
this.menu.getElement("a[href$=" + item + "]").parentNode.addClass("invisible");
return this;
},
}
// show an item
showItem: function(item) {
showItem(item) {
this.menu.getElement("a[href$=" + item + "]").parentNode.removeClass("invisible");
return this;
},
}
// enable/disable an item
setEnabled: function(item, enabled) {
setEnabled(item, enabled) {
this.menu.querySelector(`:scope a[href$="${item}"]`).parentElement.classList.toggle("disabled", !enabled);
return this;
},
}
// disable the entire menu
disable: function() {
disable() {
this.options.disabled = true;
return this;
},
}
// enable the entire menu
enable: function() {
enable() {
this.options.disabled = false;
return this;
},
}
// execute an action
execute: function(action, element) {
execute(action, element) {
if (this.options.actions[action])
this.options.actions[action](element, this, action);
return this;
}
});
};
const FilterListContextMenu = new Class({
Extends: ContextMenu,
initialize: function(options) {
this.parent(options);
class FilterListContextMenu extends ContextMenu {
constructor(options) {
super(options);
this.torrentObserver = new MutationObserver((records, observer) => {
this.updateTorrentActions();
});
},
}
startTorrentObserver: function() {
startTorrentObserver() {
this.torrentObserver.observe(torrentsTable.tableBody, { childList: true });
},
}
stopTorrentObserver: function() {
stopTorrentObserver() {
this.torrentObserver.disconnect();
},
}
updateTorrentActions: function() {
updateTorrentActions() {
const torrentsVisible = torrentsTable.tableBody.children.length > 0;
this.setEnabled("startTorrents", torrentsVisible)
.setEnabled("stopTorrents", torrentsVisible)
.setEnabled("deleteTorrents", torrentsVisible);
}
});
};
const TorrentsTableContextMenu = new Class({
Extends: ContextMenu,
updateMenuItems: function() {
class TorrentsTableContextMenu extends ContextMenu {
updateMenuItems() {
let all_are_seq_dl = true;
let there_are_seq_dl = false;
let all_are_f_l_piece_prio = true;
@ -485,9 +474,9 @@ window.qBittorrent.ContextMenu ??= (() => {
const isEqual = ((count !== undefined) && (count === selectedRows.length));
categoryIcon.classList.toggle("highlightedCategoryIcon", isEqual);
});
},
}
updateCategoriesSubMenu: function(categoryList) {
updateCategoriesSubMenu(categoryList) {
const contextCategoryList = $("contextCategoryList");
contextCategoryList.getChildren().each(c => c.destroy());
@ -540,9 +529,9 @@ window.qBittorrent.ContextMenu ??= (() => {
contextCategoryList.appendChild(setCategoryItem);
}
},
}
updateTagsSubMenu: function(tagList) {
updateTagsSubMenu(tagList) {
const contextTagList = $("contextTagList");
while (contextTagList.firstChild !== null)
contextTagList.removeChild(contextTagList.firstChild);
@ -598,18 +587,16 @@ window.qBittorrent.ContextMenu ??= (() => {
contextTagList.appendChild(setTagItem);
}
}
});
};
const StatusesFilterContextMenu = new Class({
Extends: FilterListContextMenu,
updateMenuItems: function() {
class StatusesFilterContextMenu extends FilterListContextMenu {
updateMenuItems() {
this.updateTorrentActions();
}
});
};
const CategoriesFilterContextMenu = new Class({
Extends: FilterListContextMenu,
updateMenuItems: function() {
class CategoriesFilterContextMenu extends FilterListContextMenu {
updateMenuItems() {
const id = Number(this.options.element.id);
if ((id !== CATEGORIES_ALL) && (id !== CATEGORIES_UNCATEGORIZED)) {
this.showItem("editCategory");
@ -627,11 +614,10 @@ window.qBittorrent.ContextMenu ??= (() => {
this.updateTorrentActions();
}
});
};
const TagsFilterContextMenu = new Class({
Extends: FilterListContextMenu,
updateMenuItems: function() {
class TagsFilterContextMenu extends FilterListContextMenu {
updateMenuItems() {
const id = Number(this.options.element.id);
if ((id !== TAGS_ALL) && (id !== TAGS_UNTAGGED))
this.showItem("deleteTag");
@ -640,11 +626,10 @@ window.qBittorrent.ContextMenu ??= (() => {
this.updateTorrentActions();
}
});
};
const TrackersFilterContextMenu = new Class({
Extends: FilterListContextMenu,
updateMenuItems: function() {
class TrackersFilterContextMenu extends FilterListContextMenu {
updateMenuItems() {
const id = Number(this.options.element.id);
if ((id !== TRACKERS_ALL) && (id !== TRACKERS_TRACKERLESS))
this.showItem("deleteTracker");
@ -653,12 +638,10 @@ window.qBittorrent.ContextMenu ??= (() => {
this.updateTorrentActions();
}
});
};
const SearchPluginsTableContextMenu = new Class({
Extends: ContextMenu,
updateMenuItems: function() {
class SearchPluginsTableContextMenu extends ContextMenu {
updateMenuItems() {
const enabledColumnIndex = function(text) {
const columns = $("searchPluginsTableFixedHeaderRow").getChildren("th");
for (let i = 0; i < columns.length; ++i) {
@ -672,11 +655,10 @@ window.qBittorrent.ContextMenu ??= (() => {
this.showItem("Uninstall");
}
});
};
const RssFeedContextMenu = new Class({
Extends: ContextMenu,
updateMenuItems: function() {
class RssFeedContextMenu extends ContextMenu {
updateMenuItems() {
const selectedRows = window.qBittorrent.Rss.rssFeedTable.selectedRowsIds();
this.menu.getElement("a[href$=newSubscription]").parentNode.addClass("separator");
switch (selectedRows.length) {
@ -746,15 +728,12 @@ window.qBittorrent.ContextMenu ??= (() => {
break;
}
}
});
};
const RssArticleContextMenu = new Class({
Extends: ContextMenu
});
class RssArticleContextMenu extends ContextMenu {};
const RssDownloaderRuleContextMenu = new Class({
Extends: ContextMenu,
adjustMenuPosition: function(e) {
class RssDownloaderRuleContextMenu extends ContextMenu {
adjustMenuPosition(e) {
this.updateMenuItems();
// draw the menu off-screen to know the menu dimensions
@ -774,8 +753,8 @@ window.qBittorrent.ContextMenu ??= (() => {
this.menu.style.top = `${yPosMenu}px`;
this.menu.style.position = "absolute";
this.menu.style.zIndex = "2000";
},
updateMenuItems: function() {
}
updateMenuItems() {
const selectedRows = window.qBittorrent.RssDownloader.rssDownloaderRulesTable.selectedRowsIds();
this.showItem("addRule");
switch (selectedRows.length) {
@ -799,7 +778,7 @@ window.qBittorrent.ContextMenu ??= (() => {
break;
}
}
});
};
return exports();
})();

View file

@ -291,21 +291,18 @@ window.qBittorrent.DynamicTable ??= (() => {
},
setupDynamicTableHeaderContextMenuClass: function() {
if (!DynamicTableHeaderContextMenuClass) {
DynamicTableHeaderContextMenuClass = new Class({
Extends: window.qBittorrent.ContextMenu.ContextMenu,
updateMenuItems: function() {
for (let i = 0; i < this.dynamicTable.columns.length; ++i) {
if (this.dynamicTable.columns[i].caption === "")
continue;
if (this.dynamicTable.columns[i].visible !== "0")
this.setItemChecked(this.dynamicTable.columns[i].name, true);
else
this.setItemChecked(this.dynamicTable.columns[i].name, false);
}
DynamicTableHeaderContextMenuClass ??= class extends window.qBittorrent.ContextMenu.ContextMenu {
updateMenuItems() {
for (let i = 0; i < this.dynamicTable.columns.length; ++i) {
if (this.dynamicTable.columns[i].caption === "")
continue;
if (this.dynamicTable.columns[i].visible !== "0")
this.setItemChecked(this.dynamicTable.columns[i].name, true);
else
this.setItemChecked(this.dynamicTable.columns[i].name, false);
}
});
}
}
};
},
showColumn: function(columnName, show) {