mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-07-11 07:46:17 -07:00
Redesign Web API
Normalize Web API method names. Allow to use alternative Web UI. Switch Web API version to standard form (i.e. "2.0"). Improve Web UI translation code. Retranslate changed files. Add Web API for RSS subsystem.
This commit is contained in:
parent
0fc1ad664f
commit
27d8dbf13b
90 changed files with 4817 additions and 3038 deletions
388
src/webui/www/private/scripts/contextmenu.js
Normal file
388
src/webui/www/private/scripts/contextmenu.js
Normal file
|
@ -0,0 +1,388 @@
|
|||
var lastShownContexMenu = null;
|
||||
var ContextMenu = new Class({
|
||||
//implements
|
||||
Implements: [Options, Events],
|
||||
|
||||
//options
|
||||
options: {
|
||||
actions: {},
|
||||
menu: 'menu_id',
|
||||
stopEvent: true,
|
||||
targets: 'body',
|
||||
trigger: 'contextmenu',
|
||||
offsets: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
onShow: $empty,
|
||||
onHide: $empty,
|
||||
onClick: $empty,
|
||||
fadeSpeed: 200
|
||||
},
|
||||
|
||||
//initialization
|
||||
initialize: function(options) {
|
||||
//set options
|
||||
this.setOptions(options);
|
||||
|
||||
//option diffs menu
|
||||
this.menu = $(this.options.menu);
|
||||
this.targets = $$(this.options.targets);
|
||||
|
||||
//fx
|
||||
this.fx = new Fx.Tween(this.menu, {
|
||||
property: 'opacity',
|
||||
duration: this.options.fadeSpeed,
|
||||
onComplete: function() {
|
||||
if (this.getStyle('opacity')) {
|
||||
this.setStyle('visibility', 'visible');
|
||||
}
|
||||
else {
|
||||
this.setStyle('visibility', 'hidden');
|
||||
}
|
||||
}.bind(this.menu)
|
||||
});
|
||||
|
||||
//hide and begin the listener
|
||||
this.hide().startListener();
|
||||
|
||||
//hide the menu
|
||||
this.menu.setStyles({
|
||||
'position': 'absolute',
|
||||
'top': '-900000px',
|
||||
'display': 'block'
|
||||
});
|
||||
},
|
||||
|
||||
adjustMenuPosition: function(e) {
|
||||
this.updateMenuItems();
|
||||
|
||||
var scrollableMenuMaxHeight = document.documentElement.clientHeight * 0.75;
|
||||
|
||||
if (this.menu.hasClass('scrollableMenu'))
|
||||
this.menu.setStyle('max-height', scrollableMenuMaxHeight);
|
||||
|
||||
// draw the menu off-screen to know the menu dimentions
|
||||
this.menu.setStyles({
|
||||
left: '-999em',
|
||||
top: '-999em'
|
||||
});
|
||||
|
||||
// position the menu
|
||||
var xPosMenu = e.page.x + this.options.offsets.x;
|
||||
var yPosMenu = e.page.y + this.options.offsets.y;
|
||||
if (xPosMenu + this.menu.offsetWidth > document.documentElement.clientWidth)
|
||||
xPosMenu -= this.menu.offsetWidth;
|
||||
if (yPosMenu + this.menu.offsetHeight > document.documentElement.clientHeight)
|
||||
yPosMenu = document.documentElement.clientHeight - this.menu.offsetHeight;
|
||||
if (xPosMenu < 0)
|
||||
xPosMenu = 0;
|
||||
if (yPosMenu < 0)
|
||||
yPosMenu = 0;
|
||||
this.menu.setStyles({
|
||||
left: xPosMenu,
|
||||
top: yPosMenu,
|
||||
position: 'absolute',
|
||||
'z-index': '2000'
|
||||
});
|
||||
|
||||
// position the sub-menu
|
||||
var uls = this.menu.getElementsByTagName('ul');
|
||||
for (var i = 0; i < uls.length; i++) {
|
||||
var ul = uls[i];
|
||||
if (ul.hasClass('scrollableMenu'))
|
||||
ul.setStyle('max-height', scrollableMenuMaxHeight);
|
||||
var rectParent = ul.parentNode.getBoundingClientRect();
|
||||
var xPosOrigin = rectParent.left;
|
||||
var yPosOrigin = rectParent.bottom;
|
||||
var xPos = xPosOrigin + rectParent.width - 1;
|
||||
var yPos = yPosOrigin - rectParent.height - 1;
|
||||
if (xPos + ul.offsetWidth > document.documentElement.clientWidth)
|
||||
xPos -= (ul.offsetWidth + rectParent.width - 2);
|
||||
if (yPos + ul.offsetHeight > document.documentElement.clientHeight)
|
||||
yPos = document.documentElement.clientHeight - ul.offsetHeight;
|
||||
if (xPos < 0)
|
||||
xPos = 0;
|
||||
if (yPos < 0)
|
||||
yPos = 0;
|
||||
ul.setStyles({
|
||||
'margin-left': xPos - xPosOrigin,
|
||||
'margin-top': yPos - yPosOrigin
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
addTarget: function(t) {
|
||||
this.targets[this.targets.length] = t;
|
||||
t.addEvent(this.options.trigger, function(e) {
|
||||
//enabled?
|
||||
if (!this.options.disabled) {
|
||||
//prevent default, if told to
|
||||
if (this.options.stopEvent) {
|
||||
e.stop();
|
||||
}
|
||||
//record this as the trigger
|
||||
this.options.element = $(t);
|
||||
this.adjustMenuPosition(e);
|
||||
//show the menu
|
||||
this.show();
|
||||
}
|
||||
}.bind(this));
|
||||
t.addEvent('click', function(e) {
|
||||
this.hide();
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
//get things started
|
||||
startListener: function() {
|
||||
/* all elements */
|
||||
this.targets.each(function(el) {
|
||||
/* show the menu */
|
||||
el.addEvent(this.options.trigger, function(e) {
|
||||
//enabled?
|
||||
if (!this.options.disabled) {
|
||||
//prevent default, if told to
|
||||
if (this.options.stopEvent) {
|
||||
e.stop();
|
||||
}
|
||||
//record this as the trigger
|
||||
this.options.element = $(el);
|
||||
this.adjustMenuPosition(e);
|
||||
//show the menu
|
||||
this.show();
|
||||
}
|
||||
}.bind(this));
|
||||
el.addEvent('click', function(e) {
|
||||
this.hide();
|
||||
}.bind(this));
|
||||
}, this);
|
||||
|
||||
/* menu items */
|
||||
this.menu.getElements('a').each(function(item) {
|
||||
item.addEvent('click', function(e) {
|
||||
e.preventDefault();
|
||||
if (!item.hasClass('disabled')) {
|
||||
this.execute(item.get('href').split('#')[1], $(this.options.element));
|
||||
this.fireEvent('click', [item, e]);
|
||||
}
|
||||
}.bind(this));
|
||||
}, this);
|
||||
|
||||
//hide on body click
|
||||
$(document.body).addEvent('click', function() {
|
||||
this.hide();
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
updateMenuItems: function () {},
|
||||
|
||||
//show menu
|
||||
show: function (trigger) {
|
||||
if (lastShownContexMenu && lastShownContexMenu != this)
|
||||
lastShownContexMenu.hide();
|
||||
this.fx.start(1);
|
||||
this.fireEvent('show');
|
||||
this.shown = true;
|
||||
lastShownContexMenu = this;
|
||||
return this;
|
||||
},
|
||||
|
||||
//hide the menu
|
||||
hide: function (trigger) {
|
||||
if (this.shown) {
|
||||
this.fx.start(0);
|
||||
//this.menu.fade('out');
|
||||
this.fireEvent('hide');
|
||||
this.shown = false;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
setItemChecked: function (item, checked) {
|
||||
this.menu.getElement('a[href$=' + item + ']').firstChild.style.opacity =
|
||||
checked ? '1' : '0';
|
||||
return this;
|
||||
},
|
||||
|
||||
getItemChecked: function (item) {
|
||||
return '0' != this.menu.getElement('a[href$=' + item + ']').firstChild.style.opacity;
|
||||
},
|
||||
|
||||
//hide an item
|
||||
hideItem: function (item) {
|
||||
this.menu.getElement('a[href$=' + item + ']').parentNode.addClass('invisible');
|
||||
return this;
|
||||
},
|
||||
|
||||
//show an item
|
||||
showItem: function (item) {
|
||||
this.menu.getElement('a[href$=' + item + ']').parentNode.removeClass('invisible');
|
||||
return this;
|
||||
},
|
||||
|
||||
//disable the entire menu
|
||||
disable: function () {
|
||||
this.options.disabled = true;
|
||||
return this;
|
||||
},
|
||||
|
||||
//enable the entire menu
|
||||
enable: function () {
|
||||
this.options.disabled = false;
|
||||
return this;
|
||||
},
|
||||
|
||||
//execute an action
|
||||
execute: function (action, element) {
|
||||
if (this.options.actions[action]) {
|
||||
this.options.actions[action](element, this, action);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
var TorrentsTableContextMenu = new Class({
|
||||
Extends: ContextMenu,
|
||||
|
||||
updateMenuItems: function () {
|
||||
all_are_seq_dl = true;
|
||||
there_are_seq_dl = false;
|
||||
all_are_f_l_piece_prio = true;
|
||||
there_are_f_l_piece_prio = false;
|
||||
all_are_downloaded = true;
|
||||
all_are_paused = true;
|
||||
there_are_paused = false;
|
||||
all_are_force_start = true;
|
||||
there_are_force_start = false;
|
||||
all_are_super_seeding = true;
|
||||
all_are_auto_tmm = true;
|
||||
there_are_auto_tmm = false;
|
||||
|
||||
var h = torrentsTable.selectedRowsIds();
|
||||
h.each(function(item, index){
|
||||
var data = torrentsTable.rows.get(item).full_data;
|
||||
|
||||
if (data['seq_dl'] !== true)
|
||||
all_are_seq_dl = false;
|
||||
else
|
||||
there_are_seq_dl = true;
|
||||
|
||||
if (data['f_l_piece_prio'] !== true)
|
||||
all_are_f_l_piece_prio = false;
|
||||
else
|
||||
there_are_f_l_piece_prio = true;
|
||||
|
||||
if (data['progress'] != 1.0) // not downloaded
|
||||
all_are_downloaded = false;
|
||||
else if (data['super_seeding'] !== true)
|
||||
all_are_super_seeding = false;
|
||||
|
||||
if (data['state'] != 'pausedUP' && data['state'] != 'pausedDL')
|
||||
all_are_paused = false;
|
||||
else
|
||||
there_are_paused = true;
|
||||
|
||||
if (data['force_start'] !== true)
|
||||
all_are_force_start = false;
|
||||
else
|
||||
there_are_force_start = true;
|
||||
|
||||
if (data['auto_tmm'] === true)
|
||||
there_are_auto_tmm = true;
|
||||
else
|
||||
all_are_auto_tmm = false;
|
||||
});
|
||||
|
||||
show_seq_dl = true;
|
||||
|
||||
if (!all_are_seq_dl && there_are_seq_dl)
|
||||
show_seq_dl = false;
|
||||
|
||||
show_f_l_piece_prio = true;
|
||||
|
||||
if (!all_are_f_l_piece_prio && there_are_f_l_piece_prio)
|
||||
show_f_l_piece_prio = false;
|
||||
|
||||
if (all_are_downloaded) {
|
||||
this.hideItem('DownloadLimit');
|
||||
this.menu.getElement('a[href$=UploadLimit]').parentNode.addClass('separator');
|
||||
this.hideItem('SequentialDownload');
|
||||
this.hideItem('FirstLastPiecePrio');
|
||||
this.showItem('SuperSeeding');
|
||||
this.setItemChecked('SuperSeeding', all_are_super_seeding);
|
||||
} else {
|
||||
if (!show_seq_dl && show_f_l_piece_prio)
|
||||
this.menu.getElement('a[href$=FirstLastPiecePrio]').parentNode.addClass('separator');
|
||||
else
|
||||
this.menu.getElement('a[href$=FirstLastPiecePrio]').parentNode.removeClass('separator');
|
||||
|
||||
if (show_seq_dl)
|
||||
this.showItem('SequentialDownload');
|
||||
else
|
||||
this.hideItem('SequentialDownload');
|
||||
|
||||
if (show_f_l_piece_prio)
|
||||
this.showItem('FirstLastPiecePrio');
|
||||
else
|
||||
this.hideItem('FirstLastPiecePrio');
|
||||
|
||||
this.setItemChecked('SequentialDownload', all_are_seq_dl);
|
||||
this.setItemChecked('FirstLastPiecePrio', all_are_f_l_piece_prio);
|
||||
|
||||
this.showItem('DownloadLimit');
|
||||
this.menu.getElement('a[href$=UploadLimit]').parentNode.removeClass('separator');
|
||||
this.hideItem('SuperSeeding');
|
||||
}
|
||||
|
||||
this.showItem('Start');
|
||||
this.showItem('Pause');
|
||||
this.showItem('ForceStart');
|
||||
if (all_are_paused)
|
||||
this.hideItem('Pause');
|
||||
else if (all_are_force_start)
|
||||
this.hideItem('ForceStart');
|
||||
else if (!there_are_paused && !there_are_force_start)
|
||||
this.hideItem('Start');
|
||||
|
||||
if (!all_are_auto_tmm && there_are_auto_tmm)
|
||||
this.hideItem('AutoTorrentManagement');
|
||||
else
|
||||
this.setItemChecked('AutoTorrentManagement', all_are_auto_tmm);
|
||||
|
||||
},
|
||||
|
||||
updateCategoriesSubMenu : function (category_list) {
|
||||
var categoryList = $('contextCategoryList');
|
||||
categoryList.empty();
|
||||
categoryList.appendChild(new Element('li', {html: '<a href="javascript:torrentNewCategoryFN();"><img src="theme/list-add" alt="QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]</a>'}));
|
||||
categoryList.appendChild(new Element('li', {html: '<a href="javascript:torrentSetCategoryFN(0);"><img src="theme/edit-clear" alt="QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]</a>'}));
|
||||
|
||||
var sortedCategories = [];
|
||||
Object.each(category_list, function (category) {
|
||||
sortedCategories.push(category.name);
|
||||
});
|
||||
sortedCategories.sort();
|
||||
|
||||
var first = true;
|
||||
Object.each(sortedCategories, function (categoryName) {
|
||||
var categoryHash = genHash(categoryName);
|
||||
var el = new Element('li', {html: '<a href="javascript:torrentSetCategoryFN(\'' + categoryHash + '\');"><img src="theme/inode-directory"/> ' + escapeHtml(categoryName) + '</a>'});
|
||||
if (first) {
|
||||
el.addClass('separator');
|
||||
first = false;
|
||||
}
|
||||
categoryList.appendChild(el);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var CategoriesFilterContextMenu = new Class({
|
||||
Extends: ContextMenu,
|
||||
updateMenuItems: function () {
|
||||
var id = this.options.element.id;
|
||||
if (id != CATEGORIES_ALL && id != CATEGORIES_UNCATEGORIZED)
|
||||
this.showItem('DeleteCategory');
|
||||
else
|
||||
this.hideItem('DeleteCategory');
|
||||
}
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue