mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-08-14 02:27:09 -07:00
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:
parent
7031c52d16
commit
5a0914e333
2 changed files with 107 additions and 131 deletions
|
@ -46,12 +46,9 @@ window.qBittorrent.ContextMenu ??= (() => {
|
|||
};
|
||||
|
||||
let lastShownContextMenu = null;
|
||||
const ContextMenu = new Class({
|
||||
// implements
|
||||
Implements: [Options, Events],
|
||||
|
||||
// options
|
||||
options: {
|
||||
class ContextMenu {
|
||||
constructor(options) {
|
||||
this.options = {
|
||||
actions: {},
|
||||
menu: "menu_id",
|
||||
stopEvent: true,
|
||||
|
@ -64,13 +61,9 @@ window.qBittorrent.ContextMenu ??= (() => {
|
|||
onHide: () => {},
|
||||
onClick: () => {},
|
||||
fadeSpeed: 200,
|
||||
touchTimer: 600
|
||||
},
|
||||
|
||||
// initialization
|
||||
initialize: function(options) {
|
||||
// set options
|
||||
this.setOptions(options);
|
||||
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();
|
||||
})();
|
||||
|
|
|
@ -291,10 +291,8 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
},
|
||||
|
||||
setupDynamicTableHeaderContextMenuClass: function() {
|
||||
if (!DynamicTableHeaderContextMenuClass) {
|
||||
DynamicTableHeaderContextMenuClass = new Class({
|
||||
Extends: window.qBittorrent.ContextMenu.ContextMenu,
|
||||
updateMenuItems: function() {
|
||||
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;
|
||||
|
@ -304,8 +302,7 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
this.setItemChecked(this.dynamicTable.columns[i].name, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
showColumn: function(columnName, show) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue