Move JavaScript code into explicit namespaces

This cleans up the global namespace by explicitly exporting shared values. All html and JavaScript files have been converted to use explicit exports except for client.js and mocha-init.js
This commit is contained in:
Thomas Piccirello 2019-08-11 23:53:20 -07:00
parent b144d3b797
commit 1439bcc864
32 changed files with 6204 additions and 5838 deletions

View file

@ -61,7 +61,7 @@
<p>QBT_TR(List of peers to add (one IP per line):)QBT_TR[CONTEXT=PeersAdditionDialog]</p>
<textarea id="peers" rows="10" style="width: 100%;" placeholder="QBT_TR(Format: IPv4:port / [IPv6]:port)QBT_TR[CONTEXT=PeersAdditionDialog]"></textarea>
<div style="margin-top: 10px; text-align: center;">
<button onclick="window.parent.closeWindows();">QBT_TR(Cancel)QBT_TR[CONTEXT=PeersAdditionDialog]</button>
<button onclick="parent.closeWindows();">QBT_TR(Cancel)QBT_TR[CONTEXT=PeersAdditionDialog]</button>
<button id="addPeersOk">QBT_TR(Ok)QBT_TR[CONTEXT=PeersAdditionDialog]</button>
</div>
</div>

View file

@ -27,7 +27,7 @@
<label for="autoTMM">QBT_TR(Torrent Management Mode:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
</td>
<td>
<select id="autoTMM" name="autoTMM" onchange="changeTMM(this)">
<select id="autoTMM" name="autoTMM" onchange="qBittorrent.Download.changeTMM(this)">
<option selected value="false">Manual</option>
<option value="true">Automatic</option>
</select>
@ -63,7 +63,7 @@
</td>
<td>
<div class="select-watched-folder-editable">
<select id="categorySelect" onchange="changeCategorySelect(this)">
<select id="categorySelect" onchange="qBittorrent.Download.changeCategorySelect(this)">
<option selected value="\other"></option>
</select>
<input name="category" type="text" value="" />

View file

@ -30,18 +30,18 @@
}).activate();
window.addEvent('domready', function() {
const uriAction = safeTrim(new URI().getData('action'));
const uriHashes = safeTrim(new URI().getData('hashes'));
const uriCategoryName = safeTrim(new URI().getData('categoryName'));
const uriSavePath = safeTrim(new URI().getData('savePath'));
const uriAction = window.qBittorrent.Misc.safeTrim(new URI().getData('action'));
const uriHashes = window.qBittorrent.Misc.safeTrim(new URI().getData('hashes'));
const uriCategoryName = window.qBittorrent.Misc.safeTrim(new URI().getData('categoryName'));
const uriSavePath = window.qBittorrent.Misc.safeTrim(new URI().getData('savePath'));
if (uriAction === "edit") {
if (!uriCategoryName)
return false;
$('categoryName').set('disabled', true);
$('categoryName').set('value', escapeHtml(uriCategoryName));
$('savePath').set('value', escapeHtml(uriSavePath));
$('categoryName').set('value', window.qBittorrent.Misc.escapeHtml(uriCategoryName));
$('savePath').set('value', window.qBittorrent.Misc.escapeHtml(uriSavePath));
$('savePath').focus();
}
else {
@ -90,7 +90,7 @@
}).send();
},
onError: function() {
alert("QBT_TR(Unable to create category)QBT_TR[CONTEXT=HttpServer] " + escapeHtml(categoryName));
alert("QBT_TR(Unable to create category)QBT_TR[CONTEXT=HttpServer] " + window.qBittorrent.Misc.escapeHtml(categoryName));
}
}).send();
break;

View file

@ -30,8 +30,8 @@
}).activate();
window.addEvent('domready', function() {
const uriAction = safeTrim(new URI().getData('action'));
const uriHashes = safeTrim(new URI().getData('hashes'));
const uriAction = window.qBittorrent.Misc.safeTrim(new URI().getData('action'));
const uriHashes = window.qBittorrent.Misc.safeTrim(new URI().getData('hashes'));
if (uriAction === 'create')
$('legendText').innerText = 'QBT_TR(Tag:)QBT_TR[CONTEXT=TagFilterWidget]';

View file

@ -24,21 +24,10 @@
'use strict';
this.torrentsTable = new TorrentsTable();
const torrentTrackersTable = new TorrentTrackersTable();
const torrentPeersTable = new TorrentPeersTable();
const torrentFilesTable = new TorrentFilesTable();
const searchResultsTable = new SearchResultsTable();
const searchPluginsTable = new SearchPluginsTable();
this.torrentsTable = new window.qBittorrent.DynamicTable.TorrentsTable();
let updatePropertiesPanel = function() {};
let updateTorrentData = function() {};
let updateTrackersData = function() {};
let updateTorrentPeersData = function() {};
let updateWebSeedsData = function() {};
let updateTorrentFilesData = function() {};
this.updateMainData = function() {};
let alternativeSpeedLimits = false;
let queueing_enabled = true;
@ -365,12 +354,12 @@ window.addEvent('load', function() {
const create_link = function(hash, text, count) {
const html = '<a href="#" onclick="setCategoryFilter(' + hash + ');return false;">'
+ '<img src="images/qbt-theme/inode-directory.svg"/>'
+ escapeHtml(text) + ' (' + count + ')' + '</a>';
+ window.qBittorrent.Misc.escapeHtml(text) + ' (' + count + ')' + '</a>';
const el = new Element('li', {
id: hash,
html: html
});
categoriesFilterContextMenu.addTarget(el);
window.qBittorrent.Filters.categoriesFilterContextMenu.addTarget(el);
return el;
};
@ -422,12 +411,12 @@ window.addEvent('load', function() {
const createLink = function(hash, text, count) {
const html = '<a href="#" onclick="setTagFilter(' + hash + ');return false;">'
+ '<img src="images/qbt-theme/inode-directory.svg"/>'
+ escapeHtml(text) + ' (' + count + ')' + '</a>';
+ window.qBittorrent.Misc.escapeHtml(text) + ' (' + count + ')' + '</a>';
const el = new Element('li', {
id: hash,
html: html
});
tagsFilterContextMenu.addTarget(el);
window.qBittorrent.Filters.tagsFilterContextMenu.addTarget(el);
return el;
};
@ -579,11 +568,11 @@ window.addEvent('load', function() {
updateFiltersList();
if (update_categories) {
updateCategoryList();
torrentsTableContextMenu.updateCategoriesSubMenu(category_list);
window.qBittorrent.TransferList.contextMenu.updateCategoriesSubMenu(category_list);
}
if (updateTags) {
updateTagList();
torrentsTableContextMenu.updateTagsSubMenu(tagList);
window.qBittorrent.TransferList.contextMenu.updateTagsSubMenu(tagList);
}
if (full_update)
@ -603,39 +592,39 @@ window.addEvent('load', function() {
};
const processServerState = function() {
let transfer_info = friendlyUnit(serverState.dl_info_speed, true);
let transfer_info = window.qBittorrent.Misc.friendlyUnit(serverState.dl_info_speed, true);
if (serverState.dl_rate_limit > 0)
transfer_info += " [" + friendlyUnit(serverState.dl_rate_limit, true) + "]";
transfer_info += " (" + friendlyUnit(serverState.dl_info_data, false) + ")";
transfer_info += " [" + window.qBittorrent.Misc.friendlyUnit(serverState.dl_rate_limit, true) + "]";
transfer_info += " (" + window.qBittorrent.Misc.friendlyUnit(serverState.dl_info_data, false) + ")";
$("DlInfos").set('html', transfer_info);
transfer_info = friendlyUnit(serverState.up_info_speed, true);
transfer_info = window.qBittorrent.Misc.friendlyUnit(serverState.up_info_speed, true);
if (serverState.up_rate_limit > 0)
transfer_info += " [" + friendlyUnit(serverState.up_rate_limit, true) + "]";
transfer_info += " (" + friendlyUnit(serverState.up_info_data, false) + ")";
transfer_info += " [" + window.qBittorrent.Misc.friendlyUnit(serverState.up_rate_limit, true) + "]";
transfer_info += " (" + window.qBittorrent.Misc.friendlyUnit(serverState.up_info_data, false) + ")";
$("UpInfos").set('html', transfer_info);
if (speedInTitle) {
document.title = "QBT_TR([D: %1, U: %2] qBittorrent %3)QBT_TR[CONTEXT=MainWindow]".replace("%1", friendlyUnit(serverState.dl_info_speed, true)).replace("%2", friendlyUnit(serverState.up_info_speed, true)).replace("%3", qbtVersion());
document.title = "QBT_TR([D: %1, U: %2] qBittorrent %3)QBT_TR[CONTEXT=MainWindow]".replace("%1", window.qBittorrent.Misc.friendlyUnit(serverState.dl_info_speed, true)).replace("%2", window.qBittorrent.Misc.friendlyUnit(serverState.up_info_speed, true)).replace("%3", qbtVersion());
document.title += " QBT_TR(Web UI)QBT_TR[CONTEXT=OptionsDialog]";
}
else
document.title = ("qBittorrent " + qbtVersion() + " QBT_TR(Web UI)QBT_TR[CONTEXT=OptionsDialog]");
$('freeSpaceOnDisk').set('html', 'QBT_TR(Free space: %1)QBT_TR[CONTEXT=HttpServer]'.replace("%1", friendlyUnit(serverState.free_space_on_disk)));
$('freeSpaceOnDisk').set('html', 'QBT_TR(Free space: %1)QBT_TR[CONTEXT=HttpServer]'.replace("%1", window.qBittorrent.Misc.friendlyUnit(serverState.free_space_on_disk)));
$('DHTNodes').set('html', 'QBT_TR(DHT: %1 nodes)QBT_TR[CONTEXT=StatusBar]'.replace("%1", serverState.dht_nodes));
// Statistics dialog
if (document.getElementById("statisticspage")) {
$('AlltimeDL').set('html', friendlyUnit(serverState.alltime_dl, false));
$('AlltimeUL').set('html', friendlyUnit(serverState.alltime_ul, false));
$('TotalWastedSession').set('html', friendlyUnit(serverState.total_wasted_session, false));
$('AlltimeDL').set('html', window.qBittorrent.Misc.friendlyUnit(serverState.alltime_dl, false));
$('AlltimeUL').set('html', window.qBittorrent.Misc.friendlyUnit(serverState.alltime_ul, false));
$('TotalWastedSession').set('html', window.qBittorrent.Misc.friendlyUnit(serverState.total_wasted_session, false));
$('GlobalRatio').set('html', serverState.global_ratio);
$('TotalPeerConnections').set('html', serverState.total_peer_connections);
$('ReadCacheHits').set('html', serverState.read_cache_hits + "%");
$('TotalBuffersSize').set('html', friendlyUnit(serverState.total_buffers_size, false));
$('TotalBuffersSize').set('html', window.qBittorrent.Misc.friendlyUnit(serverState.total_buffers_size, false));
$('WriteCacheOverload').set('html', serverState.write_cache_overload + "%");
$('ReadCacheOverload').set('html', serverState.read_cache_overload + "%");
$('QueuedIOJobs').set('html', serverState.queued_io_jobs);
$('AverageTimeInQueue').set('html', serverState.average_time_queue + " ms");
$('TotalQueuedSize').set('html', friendlyUnit(serverState.total_queued_size, false));
$('TotalQueuedSize').set('html', window.qBittorrent.Misc.friendlyUnit(serverState.total_queued_size, false));
}
if (serverState.connection_status == "connected")
@ -790,7 +779,7 @@ window.addEvent('load', function() {
const showSearchTab = function() {
if (!searchTabInitialized) {
initSearchTab();
window.qBittorrent.Search.init();
searchTabInitialized = true;
}
@ -878,16 +867,26 @@ window.addEvent('load', function() {
MochaUI.initializeTabs('propertiesTabs');
updatePropertiesPanel = function() {
if (!$('prop_general').hasClass('invisible'))
updateTorrentData();
else if (!$('prop_trackers').hasClass('invisible'))
updateTrackersData();
else if (!$('prop_peers').hasClass('invisible'))
updateTorrentPeersData();
else if (!$('prop_webseeds').hasClass('invisible'))
updateWebSeedsData();
else if (!$('prop_files').hasClass('invisible'))
updateTorrentFilesData();
if (!$('prop_general').hasClass('invisible')) {
if (window.qBittorrent.PropGeneral !== undefined)
window.qBittorrent.PropGeneral.updateData();
}
else if (!$('prop_trackers').hasClass('invisible')) {
if (window.qBittorrent.PropTrackers !== undefined)
window.qBittorrent.PropTrackers.updateData();
}
else if (!$('prop_peers').hasClass('invisible')) {
if (window.qBittorrent.PropPeers !== undefined)
window.qBittorrent.PropPeers.updateData();
}
else if (!$('prop_webseeds').hasClass('invisible')) {
if (window.qBittorrent.PropWebseeds !== undefined)
window.qBittorrent.PropWebseeds.updateData();
}
else if (!$('prop_files').hasClass('invisible')) {
if (window.qBittorrent.PropFiles !== undefined)
window.qBittorrent.PropFiles.updateData();
}
};
$('PropGeneralLink').addEvent('click', function(e) {

View file

@ -28,497 +28,515 @@
'use strict';
let lastShownContextMenu = null;
const ContextMenu = new Class({
//implements
Implements: [Options, Events],
if (window.qBittorrent === undefined) {
window.qBittorrent = {};
}
//options
options: {
actions: {},
menu: 'menu_id',
stopEvent: true,
targets: 'body',
offsets: {
x: 0,
y: 0
window.qBittorrent.ContextMenu = (function() {
const exports = function() {
return {
ContextMenu: ContextMenu,
TorrentsTableContextMenu: TorrentsTableContextMenu,
CategoriesFilterContextMenu: CategoriesFilterContextMenu,
TagsFilterContextMenu: TagsFilterContextMenu,
SearchPluginsTableContextMenu: SearchPluginsTableContextMenu
};
};
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: $empty,
onHide: $empty,
onClick: $empty,
fadeSpeed: 200,
touchTimer: 600
},
onShow: $empty,
onHide: $empty,
onClick: $empty,
fadeSpeed: 200,
touchTimer: 600
},
//initialization
initialize: function(options) {
//set options
this.setOptions(options);
//initialization
initialize: function(options) {
//set options
this.setOptions(options);
//option diffs menu
this.menu = $(this.options.menu);
this.targets = $$(this.options.targets);
//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)
});
//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 and begin the listener
this.hide().startListener();
//hide the menu
this.menu.setStyles({
'position': 'absolute',
'top': '-900000px',
'display': 'block'
});
},
adjustMenuPosition: function(e) {
this.updateMenuItems();
const 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 dimensions
this.menu.setStyles({
left: '-999em',
top: '-999em'
});
// position the menu
let xPosMenu = e.page.x + this.options.offsets.x;
let 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
const uls = this.menu.getElementsByTagName('ul');
for (let i = 0; i < uls.length; ++i) {
const ul = uls[i];
if (ul.hasClass('scrollableMenu'))
ul.setStyle('max-height', scrollableMenuMaxHeight);
const rectParent = ul.parentNode.getBoundingClientRect();
const xPosOrigin = rectParent.left;
const yPosOrigin = rectParent.bottom;
let xPos = xPosOrigin + rectParent.width - 1;
let 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
});
}
},
setupEventListeners: function(elem) {
elem.addEvent('contextmenu', function(e) {
this.triggerMenu(e, elem);
}.bind(this));
elem.addEvent('click', function(e) {
this.hide();
}.bind(this));
elem.addEvent('touchstart', function(e) {
e.preventDefault();
clearTimeout(this.touchstartTimer);
this.hide();
const touchstartEvent = e;
this.touchstartTimer = setTimeout(function() {
this.triggerMenu(touchstartEvent, elem);
}.bind(this), this.options.touchTimer);
}.bind(this));
elem.addEvent('touchend', function(e) {
e.preventDefault();
clearTimeout(this.touchstartTimer);
}.bind(this));
},
addTarget: function(t) {
this.targets[this.targets.length] = t;
this.setupEventListeners(t);
},
triggerMenu: function(e, el) {
if (this.options.disabled)
return;
//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();
},
//get things started
startListener: function() {
/* all elements */
this.targets.each(function(el) {
this.setupEventListeners(el);
}.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 (lastShownContextMenu && lastShownContextMenu != this)
lastShownContextMenu.hide();
this.fx.start(1);
this.fireEvent('show');
this.shown = true;
lastShownContextMenu = this;
return this;
},
//hide the menu
this.menu.setStyles({
'position': 'absolute',
'top': '-900000px',
'display': 'block'
});
},
hide: function(trigger) {
if (this.shown) {
this.fx.start(0);
//this.menu.fade('out');
this.fireEvent('hide');
this.shown = false;
}
return this;
},
adjustMenuPosition: function(e) {
this.updateMenuItems();
setItemChecked: function(item, checked) {
this.menu.getElement('a[href$=' + item + ']').firstChild.style.opacity =
checked ? '1' : '0';
return this;
},
const scrollableMenuMaxHeight = document.documentElement.clientHeight * 0.75;
getItemChecked: function(item) {
return '0' != this.menu.getElement('a[href$=' + item + ']').firstChild.style.opacity;
},
if (this.menu.hasClass('scrollableMenu'))
this.menu.setStyle('max-height', scrollableMenuMaxHeight);
//hide an item
hideItem: function(item) {
this.menu.getElement('a[href$=' + item + ']').parentNode.addClass('invisible');
return this;
},
// draw the menu off-screen to know the menu dimensions
this.menu.setStyles({
left: '-999em',
top: '-999em'
});
//show an item
showItem: function(item) {
this.menu.getElement('a[href$=' + item + ']').parentNode.removeClass('invisible');
return this;
},
// position the menu
let xPosMenu = e.page.x + this.options.offsets.x;
let 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'
});
//disable the entire menu
disable: function() {
this.options.disabled = true;
return this;
},
// position the sub-menu
const uls = this.menu.getElementsByTagName('ul');
for (let i = 0; i < uls.length; ++i) {
const ul = uls[i];
if (ul.hasClass('scrollableMenu'))
ul.setStyle('max-height', scrollableMenuMaxHeight);
const rectParent = ul.parentNode.getBoundingClientRect();
const xPosOrigin = rectParent.left;
const yPosOrigin = rectParent.bottom;
let xPos = xPosOrigin + rectParent.width - 1;
let 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
});
//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;
}
},
});
setupEventListeners: function(elem) {
elem.addEvent('contextmenu', function(e) {
this.triggerMenu(e, elem);
}.bind(this));
elem.addEvent('click', function(e) {
this.hide();
}.bind(this));
const TorrentsTableContextMenu = new Class({
Extends: ContextMenu,
elem.addEvent('touchstart', function(e) {
e.preventDefault();
clearTimeout(this.touchstartTimer);
this.hide();
updateMenuItems: function() {
let all_are_seq_dl = true;
let there_are_seq_dl = false;
let all_are_f_l_piece_prio = true;
let there_are_f_l_piece_prio = false;
let all_are_downloaded = true;
let all_are_paused = true;
let there_are_paused = false;
let all_are_force_start = true;
let there_are_force_start = false;
let all_are_super_seeding = true;
let all_are_auto_tmm = true;
let there_are_auto_tmm = false;
const tagsSelectionState = Object.clone(tagList);
const touchstartEvent = e;
this.touchstartTimer = setTimeout(function() {
this.triggerMenu(touchstartEvent, elem);
}.bind(this), this.options.touchTimer);
}.bind(this));
elem.addEvent('touchend', function(e) {
e.preventDefault();
clearTimeout(this.touchstartTimer);
}.bind(this));
},
const h = torrentsTable.selectedRowsIds();
h.each(function(item, index) {
const data = torrentsTable.rows.get(item).full_data;
addTarget: function(t) {
this.targets[this.targets.length] = t;
this.setupEventListeners(t);
},
triggerMenu: function(e, el) {
if (this.options.disabled)
return;
//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();
},
//get things started
startListener: function() {
/* all elements */
this.targets.each(function(el) {
this.setupEventListeners(el);
}.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 (lastShownContextMenu && lastShownContextMenu != this)
lastShownContextMenu.hide();
this.fx.start(1);
this.fireEvent('show');
this.shown = true;
lastShownContextMenu = 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;
}
});
const TorrentsTableContextMenu = new Class({
Extends: ContextMenu,
updateMenuItems: function() {
let all_are_seq_dl = true;
let there_are_seq_dl = false;
let all_are_f_l_piece_prio = true;
let there_are_f_l_piece_prio = false;
let all_are_downloaded = true;
let all_are_paused = true;
let there_are_paused = false;
let all_are_force_start = true;
let there_are_force_start = false;
let all_are_super_seeding = true;
let all_are_auto_tmm = true;
let there_are_auto_tmm = false;
const tagsSelectionState = Object.clone(tagList);
const h = torrentsTable.selectedRowsIds();
h.each(function(item, index) {
const 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;
const torrentTags = data['tags'].split(', ');
for (const key in tagsSelectionState) {
const tag = tagsSelectionState[key];
const tagExists = torrentTags.contains(tag.name);
if ((tag.checked !== undefined) && (tag.checked != tagExists))
tag.indeterminate = true;
if (tag.checked === undefined)
tag.checked = tagExists;
if (data['seq_dl'] !== true)
all_are_seq_dl = false;
else
tag.checked = tag.checked && tagExists;
}
});
there_are_seq_dl = true;
let show_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 (!all_are_seq_dl && there_are_seq_dl)
show_seq_dl = false;
if (data['progress'] != 1.0) // not downloaded
all_are_downloaded = false;
else if (data['super_seeding'] !== true)
all_are_super_seeding = false;
let show_f_l_piece_prio = true;
if (data['state'] != 'pausedUP' && data['state'] != 'pausedDL')
all_are_paused = false;
else
there_are_paused = true;
if (!all_are_f_l_piece_prio && there_are_f_l_piece_prio)
show_f_l_piece_prio = false;
if (data['force_start'] !== true)
all_are_force_start = false;
else
there_are_force_start = true;
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 (data['auto_tmm'] === true)
there_are_auto_tmm = true;
else
all_are_auto_tmm = false;
if (show_seq_dl)
this.showItem('sequentialDownload');
else
const torrentTags = data['tags'].split(', ');
for (const key in tagsSelectionState) {
const tag = tagsSelectionState[key];
const tagExists = torrentTags.contains(tag.name);
if ((tag.checked !== undefined) && (tag.checked != tagExists))
tag.indeterminate = true;
if (tag.checked === undefined)
tag.checked = tagExists;
else
tag.checked = tag.checked && tagExists;
}
});
let show_seq_dl = true;
if (!all_are_seq_dl && there_are_seq_dl)
show_seq_dl = false;
let 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');
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.showItem('autoTorrentManagement');
this.setItemChecked('autoTorrentManagement', all_are_auto_tmm);
}
const contextTagList = $('contextTagList');
for (const tagHash in tagList) {
const checkbox = contextTagList.getElement('a[href=#Tag/' + tagHash + '] input[type=checkbox]');
const checkboxState = tagsSelectionState[tagHash];
checkbox.indeterminate = checkboxState.indeterminate;
checkbox.checked = checkboxState.checked;
}
},
updateCategoriesSubMenu: function(category_list) {
const categoryList = $('contextCategoryList');
categoryList.empty();
categoryList.appendChild(new Element('li', {
html: '<a href="javascript:torrentNewCategoryFN();"><img src="images/qbt-theme/list-add.svg" 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="images/qbt-theme/edit-clear.svg" alt="QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]</a>'
}));
const sortedCategories = [];
Object.each(category_list, function(category) {
sortedCategories.push(category.name);
});
sortedCategories.sort();
let first = true;
Object.each(sortedCategories, function(categoryName) {
const categoryHash = genHash(categoryName);
const el = new Element('li', {
html: '<a href="javascript:torrentSetCategoryFN(\'' + categoryHash + '\');"><img src="images/qbt-theme/inode-directory.svg"/> ' + escapeHtml(categoryName) + '</a>'
});
if (first) {
el.addClass('separator');
first = false;
this.showItem('superSeeding');
this.setItemChecked('superSeeding', all_are_super_seeding);
}
categoryList.appendChild(el);
});
},
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');
updateTagsSubMenu: function(tagList) {
const contextTagList = $('contextTagList');
while (contextTagList.firstChild !== null)
contextTagList.removeChild(contextTagList.firstChild);
if (show_seq_dl)
this.showItem('sequentialDownload');
else
this.hideItem('sequentialDownload');
contextTagList.appendChild(new Element('li', {
html: '<a href="javascript:torrentAddTagsFN();">'
+ '<img src="images/qbt-theme/list-add.svg" alt="QBT_TR(Add...)QBT_TR[CONTEXT=TransferListWidget]"/>'
+ ' QBT_TR(Add...)QBT_TR[CONTEXT=TransferListWidget]'
+ '</a>'
}));
contextTagList.appendChild(new Element('li', {
html: '<a href="javascript:torrentRemoveAllTagsFN();">'
+ '<img src="images/qbt-theme/edit-clear.svg" alt="QBT_TR(Remove All)QBT_TR[CONTEXT=TransferListWidget]"/>'
+ ' QBT_TR(Remove All)QBT_TR[CONTEXT=TransferListWidget]'
+ '</a>'
}));
if (show_f_l_piece_prio)
this.showItem('firstLastPiecePrio');
else
this.hideItem('firstLastPiecePrio');
const sortedTags = [];
for (const key in tagList)
sortedTags.push(tagList[key].name);
sortedTags.sort();
this.setItemChecked('sequentialDownload', all_are_seq_dl);
this.setItemChecked('firstLastPiecePrio', all_are_f_l_piece_prio);
for (let i = 0; i < sortedTags.length; ++i) {
const tagName = sortedTags[i];
const tagHash = genHash(tagName);
const el = new Element('li', {
html: '<a href="#Tag/' + tagHash + '" onclick="event.preventDefault(); torrentSetTagsFN(\'' + tagHash + '\', !event.currentTarget.getElement(\'input[type=checkbox]\').checked);">'
+ '<input type="checkbox" onclick="this.checked = !this.checked;"> ' + escapeHtml(tagName)
+ '</a>'
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.showItem('autoTorrentManagement');
this.setItemChecked('autoTorrentManagement', all_are_auto_tmm);
}
const contextTagList = $('contextTagList');
for (const tagHash in tagList) {
const checkbox = contextTagList.getElement('a[href=#Tag/' + tagHash + '] input[type=checkbox]');
const checkboxState = tagsSelectionState[tagHash];
checkbox.indeterminate = checkboxState.indeterminate;
checkbox.checked = checkboxState.checked;
}
},
updateCategoriesSubMenu: function(category_list) {
const categoryList = $('contextCategoryList');
categoryList.empty();
categoryList.appendChild(new Element('li', {
html: '<a href="javascript:torrentNewCategoryFN();"><img src="images/qbt-theme/list-add.svg" 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="images/qbt-theme/edit-clear.svg" alt="QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]</a>'
}));
const sortedCategories = [];
Object.each(category_list, function(category) {
sortedCategories.push(category.name);
});
if (i === 0)
el.addClass('separator');
contextTagList.appendChild(el);
sortedCategories.sort();
let first = true;
Object.each(sortedCategories, function(categoryName) {
const categoryHash = genHash(categoryName);
const el = new Element('li', {
html: '<a href="javascript:torrentSetCategoryFN(\'' + categoryHash + '\');"><img src="images/qbt-theme/inode-directory.svg"/> ' + window.qBittorrent.Misc.escapeHtml(categoryName) + '</a>'
});
if (first) {
el.addClass('separator');
first = false;
}
categoryList.appendChild(el);
});
},
updateTagsSubMenu: function(tagList) {
const contextTagList = $('contextTagList');
while (contextTagList.firstChild !== null)
contextTagList.removeChild(contextTagList.firstChild);
contextTagList.appendChild(new Element('li', {
html: '<a href="javascript:torrentAddTagsFN();">'
+ '<img src="images/qbt-theme/list-add.svg" alt="QBT_TR(Add...)QBT_TR[CONTEXT=TransferListWidget]"/>'
+ ' QBT_TR(Add...)QBT_TR[CONTEXT=TransferListWidget]'
+ '</a>'
}));
contextTagList.appendChild(new Element('li', {
html: '<a href="javascript:torrentRemoveAllTagsFN();">'
+ '<img src="images/qbt-theme/edit-clear.svg" alt="QBT_TR(Remove All)QBT_TR[CONTEXT=TransferListWidget]"/>'
+ ' QBT_TR(Remove All)QBT_TR[CONTEXT=TransferListWidget]'
+ '</a>'
}));
const sortedTags = [];
for (const key in tagList)
sortedTags.push(tagList[key].name);
sortedTags.sort();
for (let i = 0; i < sortedTags.length; ++i) {
const tagName = sortedTags[i];
const tagHash = genHash(tagName);
const el = new Element('li', {
html: '<a href="#Tag/' + tagHash + '" onclick="event.preventDefault(); torrentSetTagsFN(\'' + tagHash + '\', !event.currentTarget.getElement(\'input[type=checkbox]\').checked);">'
+ '<input type="checkbox" onclick="this.checked = !this.checked;"> ' + window.qBittorrent.Misc.escapeHtml(tagName)
+ '</a>'
});
if (i === 0)
el.addClass('separator');
contextTagList.appendChild(el);
}
}
}
});
});
const CategoriesFilterContextMenu = new Class({
Extends: ContextMenu,
updateMenuItems: function() {
const id = this.options.element.id;
if ((id != CATEGORIES_ALL) && (id != CATEGORIES_UNCATEGORIZED)) {
this.showItem('editCategory');
this.showItem('deleteCategory');
const CategoriesFilterContextMenu = new Class({
Extends: ContextMenu,
updateMenuItems: function() {
const id = this.options.element.id;
if ((id != CATEGORIES_ALL) && (id != CATEGORIES_UNCATEGORIZED)) {
this.showItem('editCategory');
this.showItem('deleteCategory');
}
else {
this.hideItem('editCategory');
this.hideItem('deleteCategory');
}
}
else {
this.hideItem('editCategory');
this.hideItem('deleteCategory');
});
const TagsFilterContextMenu = new Class({
Extends: ContextMenu,
updateMenuItems: function() {
const id = this.options.element.id;
if ((id !== TAGS_ALL.toString()) && (id !== TAGS_UNTAGGED.toString()))
this.showItem('deleteTag');
else
this.hideItem('deleteTag');
}
}
});
});
const TagsFilterContextMenu = new Class({
Extends: ContextMenu,
updateMenuItems: function() {
const id = this.options.element.id;
if ((id !== TAGS_ALL.toString()) && (id !== TAGS_UNTAGGED.toString()))
this.showItem('deleteTag');
else
this.hideItem('deleteTag');
}
});
const SearchPluginsTableContextMenu = new Class({
Extends: ContextMenu,
const SearchPluginsTableContextMenu = new Class({
Extends: ContextMenu,
updateMenuItems: function() {
const enabledColumnIndex = function(text) {
const columns = $("searchPluginsTableFixedHeaderRow").getChildren("th");
for (let i = 0; i < columns.length; ++i)
if (columns[i].get("html") === "Enabled")
return i;
};
updateMenuItems: function() {
const enabledColumnIndex = function(text) {
const columns = $("searchPluginsTableFixedHeaderRow").getChildren("th");
for (let i = 0; i < columns.length; ++i)
if (columns[i].get("html") === "Enabled")
return i;
};
this.showItem('Enabled');
this.setItemChecked('Enabled', this.options.element.getChildren("td")[enabledColumnIndex()].get("html") === "Yes");
this.showItem('Enabled');
this.setItemChecked('Enabled', this.options.element.getChildren("td")[enabledColumnIndex()].get("html") === "Yes");
this.showItem('Uninstall');
}
});
this.showItem('Uninstall');
}
});
return exports();
})();

View file

@ -23,98 +23,113 @@
'use strict';
let categories = {};
let defaultSavePath = "";
if (window.qBittorrent === undefined) {
window.qBittorrent = {};
}
const getCategories = function() {
new Request.JSON({
url: 'api/v2/torrents/categories',
noCache: true,
method: 'get',
onSuccess: function(data) {
if (data) {
categories = data;
for (const i in data) {
const category = data[i];
const option = new Element("option");
option.set('value', category.name);
option.set('html', category.name);
$('categorySelect').appendChild(option);
window.qBittorrent.Download = (function() {
const exports = function() {
return {
changeCategorySelect: changeCategorySelect,
changeTMM: changeTMM
};
};
let categories = {};
let defaultSavePath = "";
const getCategories = function() {
new Request.JSON({
url: 'api/v2/torrents/categories',
noCache: true,
method: 'get',
onSuccess: function(data) {
if (data) {
categories = data;
for (const i in data) {
const category = data[i];
const option = new Element("option");
option.set('value', category.name);
option.set('html', category.name);
$('categorySelect').appendChild(option);
}
}
}
}
}).send();
};
}).send();
};
const getPreferences = function() {
new Request.JSON({
url: 'api/v2/app/preferences',
method: 'get',
noCache: true,
onFailure: function() {
alert("Could not contact qBittorrent");
},
onSuccess: function(pref) {
if (!pref)
return;
const getPreferences = function() {
new Request.JSON({
url: 'api/v2/app/preferences',
method: 'get',
noCache: true,
onFailure: function() {
alert("Could not contact qBittorrent");
},
onSuccess: function(pref) {
if (!pref)
return;
defaultSavePath = pref.save_path;
$('savepath').setProperty('value', defaultSavePath);
$('rootFolder').checked = pref.create_subfolder_enabled;
$('startTorrent').checked = !pref.start_paused_enabled;
defaultSavePath = pref.save_path;
$('savepath').setProperty('value', defaultSavePath);
$('rootFolder').checked = pref.create_subfolder_enabled;
$('startTorrent').checked = !pref.start_paused_enabled;
if (pref.auto_tmm_enabled == 1) {
$('autoTMM').selectedIndex = 1;
$('savepath').disabled = true;
if (pref.auto_tmm_enabled == 1) {
$('autoTMM').selectedIndex = 1;
$('savepath').disabled = true;
}
else {
$('autoTMM').selectedIndex = 0;
}
}
else {
$('autoTMM').selectedIndex = 0;
}).send();
};
const changeCategorySelect = function(item) {
if (item.value == "\\other") {
item.nextElementSibling.hidden = false;
item.nextElementSibling.value = "";
item.nextElementSibling.select();
if ($('autoTMM').selectedIndex == 1)
$('savepath').value = defaultSavePath;
}
else {
item.nextElementSibling.hidden = true;
const text = item.options[item.selectedIndex].innerHTML;
item.nextElementSibling.value = text;
if ($('autoTMM').selectedIndex == 1) {
const categoryName = item.value;
const category = categories[categoryName];
let savePath = defaultSavePath;
if (category !== undefined)
savePath = (category['savePath'] !== "") ? category['savePath'] : (defaultSavePath + categoryName);
$('savepath').value = savePath;
}
}
}).send();
};
};
const changeCategorySelect = function(item) {
if (item.value == "\\other") {
item.nextElementSibling.hidden = false;
item.nextElementSibling.value = "";
item.nextElementSibling.select();
const changeTMM = function(item) {
if (item.selectedIndex == 1) {
$('savepath').disabled = true;
if ($('autoTMM').selectedIndex == 1)
$('savepath').value = defaultSavePath;
}
else {
item.nextElementSibling.hidden = true;
const text = item.options[item.selectedIndex].innerHTML;
item.nextElementSibling.value = text;
if ($('autoTMM').selectedIndex == 1) {
const categoryName = item.value;
const categorySelect = $('categorySelect');
const categoryName = categorySelect.options[categorySelect.selectedIndex].value;
const category = categories[categoryName];
let savePath = defaultSavePath;
if (category !== undefined)
savePath = (category['savePath'] !== "") ? category['savePath'] : (defaultSavePath + categoryName);
$('savepath').value = savePath;
$('savepath').value = (category === undefined) ? "" : category['savePath'];
}
}
};
else {
$('savepath').disabled = false;
$('savepath').value = defaultSavePath;
}
};
const changeTMM = function(item) {
if (item.selectedIndex == 1) {
$('savepath').disabled = true;
$(window).addEventListener("load", function() {
getPreferences();
getCategories();
});
const categorySelect = $('categorySelect');
const categoryName = categorySelect.options[categorySelect.selectedIndex].value;
const category = categories[categoryName];
$('savepath').value = (category === undefined) ? "" : category['savePath'];
}
else {
$('savepath').disabled = false;
$('savepath').value = defaultSavePath;
}
};
$(window).addEventListener("load", function() {
getPreferences();
getCategories();
});
return exports();
})();

File diff suppressed because it is too large Load diff

View file

@ -28,149 +28,167 @@
'use strict';
const FilePriority = {
"Ignored": 0,
"Normal": 1,
"High": 6,
"Maximum": 7,
"Mixed": -1
};
Object.freeze(FilePriority);
if (window.qBittorrent === undefined) {
window.qBittorrent = {};
}
const TriState = {
"Unchecked": 0,
"Checked": 1,
"Partial": 2
};
Object.freeze(TriState);
window.qBittorrent.FileTree = (function() {
const exports = function() {
return {
FilePriority: FilePriority,
TriState: TriState,
FileTree: FileTree,
FileNode: FileNode,
FolderNode: FolderNode,
};
};
const FileTree = new Class({
root: null,
nodeMap: {},
const FilePriority = {
"Ignored": 0,
"Normal": 1,
"High": 6,
"Maximum": 7,
"Mixed": -1
};
Object.freeze(FilePriority);
setRoot: function(root) {
this.root = root;
this.generateNodeMap(root);
const TriState = {
"Unchecked": 0,
"Checked": 1,
"Partial": 2
};
Object.freeze(TriState);
if (this.root.isFolder)
this.root.calculateSize();
},
const FileTree = new Class({
root: null,
nodeMap: {},
getRoot: function() {
return this.root;
},
setRoot: function(root) {
this.root = root;
this.generateNodeMap(root);
generateNodeMap: function(node) {
// don't store root node in map
if (node.root !== null) {
this.nodeMap[node.rowId] = node;
if (this.root.isFolder)
this.root.calculateSize();
},
getRoot: function() {
return this.root;
},
generateNodeMap: function(node) {
// don't store root node in map
if (node.root !== null) {
this.nodeMap[node.rowId] = node;
}
node.children.each(function(child) {
this.generateNodeMap(child);
}.bind(this));
},
getNode: function(rowId) {
return (this.nodeMap[rowId] === undefined)
? null
: this.nodeMap[rowId];
},
getRowId: function(node) {
return node.rowId;
},
/**
* Returns the nodes in dfs order
*/
toArray: function() {
const nodes = [];
this.root.children.each(function(node) {
this._getArrayOfNodes(node, nodes);
}.bind(this));
return nodes;
},
_getArrayOfNodes: function(node, array) {
array.push(node);
node.children.each(function(child) {
this._getArrayOfNodes(child, array);
}.bind(this));
}
});
node.children.each(function(child) {
this.generateNodeMap(child);
}.bind(this));
},
const FileNode = new Class({
name: "",
rowId: null,
size: 0,
checked: TriState.Unchecked,
remaining: 0,
progress: 0,
priority: FilePriority.Normal,
availability: 0,
depth: 0,
root: null,
data: null,
isFolder: false,
children: [],
});
getNode: function(rowId) {
return (this.nodeMap[rowId] === undefined)
? null
: this.nodeMap[rowId];
},
const FolderNode = new Class({
Extends: FileNode,
getRowId: function(node) {
return node.rowId;
},
initialize: function() {
this.isFolder = true;
},
/**
* Returns the nodes in dfs order
*/
toArray: function() {
const nodes = [];
this.root.children.each(function(node) {
this._getArrayOfNodes(node, nodes);
}.bind(this));
return nodes;
},
addChild(node) {
this.children.push(node);
},
_getArrayOfNodes: function(node, array) {
array.push(node);
node.children.each(function(child) {
this._getArrayOfNodes(child, array);
}.bind(this));
}
});
/**
* Recursively calculate size of node and its children
*/
calculateSize: function() {
let size = 0;
let remaining = 0;
let progress = 0;
let availability = 0;
let checked = TriState.Unchecked;
let priority = FilePriority.Normal;
const FileNode = new Class({
name: "",
rowId: null,
size: 0,
checked: TriState.Unchecked,
remaining: 0,
progress: 0,
priority: FilePriority.Normal,
availability: 0,
depth: 0,
root: null,
data: null,
isFolder: false,
children: [],
});
let isFirstFile = true;
const FolderNode = new Class({
Extends: FileNode,
this.children.each(function(node) {
if (node.isFolder)
node.calculateSize();
initialize: function() {
this.isFolder = true;
},
size += node.size;
addChild(node) {
this.children.push(node);
},
if (isFirstFile) {
priority = node.priority;
checked = node.checked;
isFirstFile = false;
}
else {
if (priority !== node.priority)
priority = FilePriority.Mixed;
if (checked !== node.checked)
checked = TriState.Partial;
}
/**
* Recursively calculate size of node and its children
*/
calculateSize: function() {
let size = 0;
let remaining = 0;
let progress = 0;
let availability = 0;
let checked = TriState.Unchecked;
let priority = FilePriority.Normal;
const isIgnored = (node.priority === FilePriority.Ignored);
if (!isIgnored) {
remaining += node.remaining;
progress += (node.progress * node.size);
availability += (node.availability * node.size);
}
}.bind(this));
let isFirstFile = true;
this.size = size;
this.remaining = remaining;
this.checked = checked;
this.progress = (progress / size);
this.priority = priority;
this.availability = (availability / size);
}
});
this.children.each(function(node) {
if (node.isFolder)
node.calculateSize();
size += node.size;
if (isFirstFile) {
priority = node.priority;
checked = node.checked;
isFirstFile = false;
}
else {
if (priority !== node.priority)
priority = FilePriority.Mixed;
if (checked !== node.checked)
checked = TriState.Partial;
}
const isIgnored = (node.priority === FilePriority.Ignored);
if (!isIgnored) {
remaining += node.remaining;
progress += (node.progress * node.size);
availability += (node.availability * node.size);
}
}.bind(this));
this.size = size;
this.remaining = remaining;
this.checked = checked;
this.progress = (progress / size);
this.priority = priority;
this.availability = (availability / size);
}
});
return exports();
})();

View file

@ -30,32 +30,49 @@
// This file is the JavaScript implementation of base/utils/fs.cpp
const QB_EXT = '.!qB';
const PathSeparator = '/';
/**
* Returns the file extension part of a file name.
*/
function fileExtension(filename) {
const name = filename.endsWith(QB_EXT)
? filename.substring(0, filename.length - QB_EXT.length)
: filename;
const pointIndex = name.lastIndexOf('.');
if (pointIndex === -1)
return '';
return name.substring(pointIndex + 1);
if (window.qBittorrent === undefined) {
window.qBittorrent = {};
}
function fileName(filepath) {
const slashIndex = filepath.lastIndexOf(PathSeparator);
if (slashIndex === -1)
return filepath;
return filepath.substring(slashIndex + 1);
}
window.qBittorrent.Filesystem = (function() {
const exports = function() {
return {
PathSeparator: PathSeparator,
fileExtension: fileExtension,
fileName: fileName,
folderName: folderName
};
};
function folderName(filepath) {
const slashIndex = filepath.lastIndexOf(PathSeparator);
if (slashIndex === -1)
return filepath;
return filepath.substring(0, slashIndex);
}
const QB_EXT = '.!qB';
const PathSeparator = '/';
/**
* Returns the file extension part of a file name.
*/
const fileExtension = function(filename) {
const name = filename.endsWith(QB_EXT)
? filename.substring(0, filename.length - QB_EXT.length)
: filename;
const pointIndex = name.lastIndexOf('.');
if (pointIndex === -1)
return '';
return name.substring(pointIndex + 1);
};
const fileName = function(filepath) {
const slashIndex = filepath.lastIndexOf(PathSeparator);
if (slashIndex === -1)
return filepath;
return filepath.substring(slashIndex + 1);
};
const folderName = function(filepath) {
const slashIndex = filepath.lastIndexOf(PathSeparator);
if (slashIndex === -1)
return filepath;
return filepath.substring(0, slashIndex);
};
return exports();
})();

View file

@ -28,166 +28,188 @@
'use strict';
/*
* JS counterpart of the function in src/misc.cpp
*/
function friendlyUnit(value, isSpeed) {
const units = [
"QBT_TR(B)QBT_TR[CONTEXT=misc]",
"QBT_TR(KiB)QBT_TR[CONTEXT=misc]",
"QBT_TR(MiB)QBT_TR[CONTEXT=misc]",
"QBT_TR(GiB)QBT_TR[CONTEXT=misc]",
"QBT_TR(TiB)QBT_TR[CONTEXT=misc]",
"QBT_TR(PiB)QBT_TR[CONTEXT=misc]",
"QBT_TR(EiB)QBT_TR[CONTEXT=misc]"
];
if ((value === undefined) || (value === null) || (value < 0))
return "QBT_TR(Unknown)QBT_TR[CONTEXT=misc]";
let i = 0;
while (value >= 1024.0 && i < 6) {
value /= 1024.0;
++i;
}
function friendlyUnitPrecision(sizeUnit) {
if (sizeUnit <= 2) return 1; // KiB, MiB
else if (sizeUnit === 3) return 2; // GiB
else return 3; // TiB, PiB, EiB
}
let ret;
if (i === 0)
ret = value + " " + units[i];
else {
const precision = friendlyUnitPrecision(i);
const offset = Math.pow(10, precision);
// Don't round up
ret = (Math.floor(offset * value) / offset).toFixed(precision) + " " + units[i];
}
if (isSpeed)
ret += "QBT_TR(/s)QBT_TR[CONTEXT=misc]";
return ret;
if (window.qBittorrent === undefined) {
window.qBittorrent = {};
}
/*
* JS counterpart of the function in src/misc.cpp
*/
function friendlyDuration(seconds) {
const MAX_ETA = 8640000;
if (seconds < 0 || seconds >= MAX_ETA)
return "∞";
if (seconds === 0)
return "0";
if (seconds < 60)
return "QBT_TR(< 1m)QBT_TR[CONTEXT=misc]";
let minutes = seconds / 60;
if (minutes < 60)
return "QBT_TR(%1m)QBT_TR[CONTEXT=misc]".replace("%1", parseInt(minutes));
let hours = minutes / 60;
minutes = minutes % 60;
if (hours < 24)
return "QBT_TR(%1h %2m)QBT_TR[CONTEXT=misc]".replace("%1", parseInt(hours)).replace("%2", parseInt(minutes));
const days = hours / 24;
hours = hours % 24;
if (days < 100)
return "QBT_TR(%1d %2h)QBT_TR[CONTEXT=misc]".replace("%1", parseInt(days)).replace("%2", parseInt(hours));
return "∞";
}
function friendlyPercentage(value) {
let percentage = (value * 100).round(1);
if (isNaN(percentage) || (percentage < 0))
percentage = 0;
if (percentage > 100)
percentage = 100;
return percentage.toFixed(1) + "%";
}
function friendlyFloat(value, precision) {
return parseFloat(value).toFixed(precision);
}
/*
* From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString
*/
if (!Date.prototype.toISOString) {
(function() {
function pad(number) {
if (number < 10) {
return '0' + number;
}
return number;
}
Date.prototype.toISOString = function() {
return this.getUTCFullYear()
+ '-' + pad(this.getUTCMonth() + 1)
+ '-' + pad(this.getUTCDate())
+ 'T' + pad(this.getUTCHours())
+ ':' + pad(this.getUTCMinutes())
+ ':' + pad(this.getUTCSeconds())
+ '.' + (this.getUTCMilliseconds() / 1000).toFixed(3).slice(2, 5)
+ 'Z';
window.qBittorrent.Misc = (function() {
const exports = function() {
return {
friendlyUnit: friendlyUnit,
friendlyDuration: friendlyDuration,
friendlyPercentage: friendlyPercentage,
friendlyFloat: friendlyFloat,
parseHtmlLinks: parseHtmlLinks,
escapeHtml: escapeHtml,
safeTrim: safeTrim,
toFixedPointString: toFixedPointString,
containsAllTerms: containsAllTerms
};
};
}());
}
/*
* JS counterpart of the function in src/misc.cpp
*/
const friendlyUnit = function(value, isSpeed) {
const units = [
"QBT_TR(B)QBT_TR[CONTEXT=misc]",
"QBT_TR(KiB)QBT_TR[CONTEXT=misc]",
"QBT_TR(MiB)QBT_TR[CONTEXT=misc]",
"QBT_TR(GiB)QBT_TR[CONTEXT=misc]",
"QBT_TR(TiB)QBT_TR[CONTEXT=misc]",
"QBT_TR(PiB)QBT_TR[CONTEXT=misc]",
"QBT_TR(EiB)QBT_TR[CONTEXT=misc]"
];
/*
* JS counterpart of the function in src/misc.cpp
*/
function parseHtmlLinks(text) {
const exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
return text.replace(exp, "<a target='_blank' href='$1'>$1</a>");
}
if ((value === undefined) || (value === null) || (value < 0))
return "QBT_TR(Unknown)QBT_TR[CONTEXT=misc]";
function escapeHtml(str) {
const div = document.createElement('div');
div.appendChild(document.createTextNode(str));
return div.innerHTML;
}
function safeTrim(value) {
try {
return value.trim();
}
catch (e) {
if (e instanceof TypeError)
return "";
throw e;
}
}
function toFixedPointString(number, digits) {
// Do not round up number
const power = Math.pow(10, digits);
return (Math.floor(power * number) / power).toFixed(digits);
}
/**
*
* @param {String} text the text to search
* @param {Array<String>} terms terms to search for within the text
* @returns {Boolean} true if all terms match the text, false otherwise
*/
function containsAllTerms(text, terms) {
const textToSearch = text.toLowerCase();
return terms.every((function(term) {
const isTermRequired = (term[0] === '+');
const isTermExcluded = (term[0] === '-');
if (isTermRequired || isTermExcluded) {
// ignore lonely +/-
if (term.length === 1)
return true;
term = term.substring(1);
let i = 0;
while (value >= 1024.0 && i < 6) {
value /= 1024.0;
++i;
}
const textContainsTerm = (textToSearch.indexOf(term) !== -1);
return isTermExcluded ? !textContainsTerm : textContainsTerm;
}));
}
function friendlyUnitPrecision(sizeUnit) {
if (sizeUnit <= 2) return 1; // KiB, MiB
else if (sizeUnit === 3) return 2; // GiB
else return 3; // TiB, PiB, EiB
}
let ret;
if (i === 0)
ret = value + " " + units[i];
else {
const precision = friendlyUnitPrecision(i);
const offset = Math.pow(10, precision);
// Don't round up
ret = (Math.floor(offset * value) / offset).toFixed(precision) + " " + units[i];
}
if (isSpeed)
ret += "QBT_TR(/s)QBT_TR[CONTEXT=misc]";
return ret;
}
/*
* JS counterpart of the function in src/misc.cpp
*/
const friendlyDuration = function(seconds) {
const MAX_ETA = 8640000;
if (seconds < 0 || seconds >= MAX_ETA)
return "∞";
if (seconds === 0)
return "0";
if (seconds < 60)
return "QBT_TR(< 1m)QBT_TR[CONTEXT=misc]";
let minutes = seconds / 60;
if (minutes < 60)
return "QBT_TR(%1m)QBT_TR[CONTEXT=misc]".replace("%1", parseInt(minutes));
let hours = minutes / 60;
minutes = minutes % 60;
if (hours < 24)
return "QBT_TR(%1h %2m)QBT_TR[CONTEXT=misc]".replace("%1", parseInt(hours)).replace("%2", parseInt(minutes));
const days = hours / 24;
hours = hours % 24;
if (days < 100)
return "QBT_TR(%1d %2h)QBT_TR[CONTEXT=misc]".replace("%1", parseInt(days)).replace("%2", parseInt(hours));
return "∞";
}
const friendlyPercentage = function(value) {
let percentage = (value * 100).round(1);
if (isNaN(percentage) || (percentage < 0))
percentage = 0;
if (percentage > 100)
percentage = 100;
return percentage.toFixed(1) + "%";
}
const friendlyFloat = function(value, precision) {
return parseFloat(value).toFixed(precision);
}
/*
* From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString
*/
if (!Date.prototype.toISOString) {
(function() {
function pad(number) {
if (number < 10) {
return '0' + number;
}
return number;
}
Date.prototype.toISOString = function() {
return this.getUTCFullYear()
+ '-' + pad(this.getUTCMonth() + 1)
+ '-' + pad(this.getUTCDate())
+ 'T' + pad(this.getUTCHours())
+ ':' + pad(this.getUTCMinutes())
+ ':' + pad(this.getUTCSeconds())
+ '.' + (this.getUTCMilliseconds() / 1000).toFixed(3).slice(2, 5)
+ 'Z';
};
}());
}
/*
* JS counterpart of the function in src/misc.cpp
*/
const parseHtmlLinks = function(text) {
const exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
return text.replace(exp, "<a target='_blank' href='$1'>$1</a>");
}
const escapeHtml = function(str) {
const div = document.createElement('div');
div.appendChild(document.createTextNode(str));
return div.innerHTML;
}
const safeTrim = function(value) {
try {
return value.trim();
}
catch (e) {
if (e instanceof TypeError)
return "";
throw e;
}
}
const toFixedPointString = function(number, digits) {
// Do not round up number
const power = Math.pow(10, digits);
return (Math.floor(power * number) / power).toFixed(digits);
}
/**
*
* @param {String} text the text to search
* @param {Array<String>} terms terms to search for within the text
* @returns {Boolean} true if all terms match the text, false otherwise
*/
const containsAllTerms = function(text, terms) {
const textToSearch = text.toLowerCase();
return terms.every((function(term) {
const isTermRequired = (term[0] === '+');
const isTermExcluded = (term[0] === '-');
if (isTermRequired || isTermExcluded) {
// ignore lonely +/-
if (term.length === 1)
return true;
term = term.substring(1);
}
const textContainsTerm = (textToSearch.indexOf(term) !== -1);
return isTermExcluded ? !textContainsTerm : textContainsTerm;
}));
}
return exports();
})();

View file

@ -38,7 +38,7 @@
----------------------------------------------------------------- */
'use strict';
const LocalPreferences = new LocalPreferencesClass();
const LocalPreferences = new window.qBittorrent.LocalPreferences.LocalPreferencesClass();
let saveWindowSize = function() {};
let loadWindowWidth = function() {};

View file

@ -28,20 +28,34 @@
'use strict';
const LocalPreferencesClass = new Class({
get: function(key, defaultValue) {
const value = localStorage.getItem(key);
return ((value === null) && (defaultValue !== undefined))
? defaultValue
: value;
},
if (window.qBittorrent === undefined) {
window.qBittorrent = {};
}
set: function(key, value) {
try {
localStorage.setItem(key, value);
window.qBittorrent.LocalPreferences = (function() {
const exports = function() {
return {
LocalPreferencesClass: LocalPreferencesClass
};
};
const LocalPreferencesClass = new Class({
get: function(key, defaultValue) {
const value = localStorage.getItem(key);
return ((value === null) && (defaultValue !== undefined))
? defaultValue
: value;
},
set: function(key, value) {
try {
localStorage.setItem(key, value);
}
catch (err) {
console.error(err);
}
}
catch (err) {
console.error(err);
}
}
})
})
return exports();
})();

View file

@ -28,113 +28,126 @@
'use strict';
const ProgressBar = new Class({
initialize: function(value, parameters) {
const vals = {
'id': 'progressbar_' + (ProgressBars++),
'value': $pick(value, 0),
'width': 0,
'height': 0,
'darkbg': '#006',
'darkfg': '#fff',
'lightbg': '#fff',
'lightfg': '#000'
if (window.qBittorrent === undefined) {
window.qBittorrent = {};
}
window.qBittorrent.ProgressBar = (function() {
const exports = function() {
return {
ProgressBar: ProgressBar
};
if (parameters && $type(parameters) == 'object') $extend(vals, parameters);
if (vals.height < 12) vals.height = 12;
const obj = new Element('div', {
'id': vals.id,
'class': 'progressbar_wrapper',
'styles': {
'border': '1px solid #000',
'width': vals.width,
'height': vals.height,
'position': 'relative',
'margin': '0 auto'
}
});
obj.vals = vals;
obj.vals.value = $pick(value, 0); // Fix by Chris
obj.vals.dark = new Element('div', {
'id': vals.id + '_dark',
'class': 'progressbar_dark',
'styles': {
'width': vals.width,
'height': vals.height,
'background': vals.darkbg,
'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,
'color': vals.lightfg,
'position': 'absolute',
'text-align': 'center',
'left': 0,
'top': 0,
'line-height': vals.height
}
});
obj.appendChild(obj.vals.dark);
obj.appendChild(obj.vals.light);
obj.getValue = ProgressBar_getValue;
obj.setValue = ProgressBar_setValue;
obj.setWidth = ProgressBar_setWidth;
if (vals.width) obj.setValue(vals.value);
else setTimeout('ProgressBar_checkForParent("' + obj.id + '")', 1);
return obj;
};
let ProgressBars = 0;
const ProgressBar = new Class({
initialize: function(value, parameters) {
const vals = {
'id': 'progressbar_' + (ProgressBars++),
'value': $pick(value, 0),
'width': 0,
'height': 0,
'darkbg': '#006',
'darkfg': '#fff',
'lightbg': '#fff',
'lightfg': '#000'
};
if (parameters && $type(parameters) == 'object') $extend(vals, parameters);
if (vals.height < 12) vals.height = 12;
const obj = new Element('div', {
'id': vals.id,
'class': 'progressbar_wrapper',
'styles': {
'border': '1px solid #000',
'width': vals.width,
'height': vals.height,
'position': 'relative',
'margin': '0 auto'
}
});
obj.vals = vals;
obj.vals.value = $pick(value, 0); // Fix by Chris
obj.vals.dark = new Element('div', {
'id': vals.id + '_dark',
'class': 'progressbar_dark',
'styles': {
'width': vals.width,
'height': vals.height,
'background': vals.darkbg,
'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,
'color': vals.lightfg,
'position': 'absolute',
'text-align': 'center',
'left': 0,
'top': 0,
'line-height': vals.height
}
});
obj.appendChild(obj.vals.dark);
obj.appendChild(obj.vals.light);
obj.getValue = ProgressBar_getValue;
obj.setValue = ProgressBar_setValue;
obj.setWidth = ProgressBar_setWidth;
if (vals.width) obj.setValue(vals.value);
else setTimeout('ProgressBar_checkForParent("' + obj.id + '")', 1);
return obj;
}
});
function ProgressBar_getValue() {
return this.vals.value;
}
});
function ProgressBar_getValue() {
return this.vals.value;
}
function ProgressBar_setValue(value) {
value = parseFloat(value);
if (isNaN(value)) value = 0;
if (value > 100) value = 100;
if (value < 0) value = 0;
this.vals.value = value;
this.vals.dark.empty();
this.vals.light.empty();
this.vals.dark.appendText(value.round(1).toFixed(1) + '%');
this.vals.light.appendText(value.round(1).toFixed(1) + '%');
const r = parseInt(this.vals.width * (value / 100));
this.vals.dark.setStyle('clip', 'rect(0,' + r + 'px,' + this.vals.height + 'px,0)');
this.vals.light.setStyle('clip', 'rect(0,' + this.vals.width + 'px,' + this.vals.height + 'px,' + r + 'px)');
}
function ProgressBar_setWidth(value) {
if (this.vals.width !== value) {
this.vals.width = value;
this.setStyle('width', value);
this.vals.dark.setStyle('width', value);
this.vals.light.setStyle('width', value);
this.setValue(this.vals.value);
function ProgressBar_setValue(value) {
value = parseFloat(value);
if (isNaN(value)) value = 0;
if (value > 100) value = 100;
if (value < 0) value = 0;
this.vals.value = value;
this.vals.dark.empty();
this.vals.light.empty();
this.vals.dark.appendText(value.round(1).toFixed(1) + '%');
this.vals.light.appendText(value.round(1).toFixed(1) + '%');
const r = parseInt(this.vals.width * (value / 100));
this.vals.dark.setStyle('clip', 'rect(0,' + r + 'px,' + this.vals.height + 'px,0)');
this.vals.light.setStyle('clip', 'rect(0,' + this.vals.width + 'px,' + this.vals.height + 'px,' + r + 'px)');
}
}
function ProgressBar_checkForParent(id) {
const obj = $(id);
if (!obj) return;
if (!obj.parentNode) return setTimeout('ProgressBar_checkForParent("' + id + '")', 1);
obj.setStyle('width', '100%');
const w = obj.offsetWidth;
obj.vals.dark.setStyle('width', w);
obj.vals.light.setStyle('width', w);
obj.vals.width = w;
obj.setValue(obj.vals.value);
}
function ProgressBar_setWidth(value) {
if (this.vals.width !== value) {
this.vals.width = value;
this.setStyle('width', value);
this.vals.dark.setStyle('width', value);
this.vals.light.setStyle('width', value);
this.setValue(this.vals.value);
}
}
let ProgressBars = 0;
function ProgressBar_checkForParent(id) {
const obj = $(id);
if (!obj) return;
if (!obj.parentNode) return setTimeout('ProgressBar_checkForParent("' + id + '")', 1);
obj.setStyle('width', '100%');
const w = obj.offsetWidth;
obj.vals.dark.setStyle('width', w);
obj.vals.light.setStyle('width', w);
obj.vals.width = w;
obj.setValue(obj.vals.value);
}
return exports();
})();

File diff suppressed because it is too large Load diff

View file

@ -28,172 +28,186 @@
'use strict';
const clearData = function() {
$('time_elapsed').set('html', '');
$('eta').set('html', '');
$('nb_connections').set('html', '');
$('total_downloaded').set('html', '');
$('total_uploaded').set('html', '');
$('dl_speed').set('html', '');
$('up_speed').set('html', '');
$('dl_limit').set('html', '');
$('up_limit').set('html', '');
$('total_wasted').set('html', '');
$('seeds').set('html', '');
$('peers').set('html', '');
$('share_ratio').set('html', '');
$('reannounce').set('html', '');
$('last_seen').set('html', '');
$('total_size').set('html', '');
$('pieces').set('html', '');
$('created_by').set('html', '');
$('addition_date').set('html', '');
$('completion_date').set('html', '');
$('creation_date').set('html', '');
$('torrent_hash').set('html', '');
$('save_path').set('html', '');
$('comment').set('html', '');
};
if (window.qBittorrent === undefined) {
window.qBittorrent = {};
}
let loadTorrentDataTimer;
const loadTorrentData = function() {
if ($('prop_general').hasClass('invisible')
|| $('propertiesPanel_collapseToggle').hasClass('panel-expand')) {
// Tab changed, don't do anything
return;
}
const current_hash = torrentsTable.getCurrentTorrentHash();
if (current_hash === "") {
clearData();
clearTimeout(loadTorrentDataTimer);
loadTorrentDataTimer = loadTorrentData.delay(5000);
return;
}
// Display hash
$('torrent_hash').set('html', current_hash);
const url = new URI('api/v2/torrents/properties?hash=' + current_hash);
new Request.JSON({
url: url,
noCache: true,
method: 'get',
onFailure: function() {
$('error_div').set('html', 'QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]');
clearTimeout(loadTorrentDataTimer);
loadTorrentDataTimer = loadTorrentData.delay(10000);
},
onSuccess: function(data) {
$('error_div').set('html', '');
if (data) {
let temp;
// Update Torrent data
if (data.seeding_time > 0)
temp = "QBT_TR(%1 (%2 this session))QBT_TR[CONTEXT=PropertiesWidget]"
.replace("%1", friendlyDuration(data.time_elapsed))
.replace("%2", friendlyDuration(data.seeding_time));
else
temp = friendlyDuration(data.time_elapsed);
$('time_elapsed').set('html', temp);
window.qBittorrent.PropGeneral = (function() {
const exports = function() {
return {
updateData: updateData
};
};
$('eta').set('html', friendlyDuration(data.eta));
const clearData = function() {
$('time_elapsed').set('html', '');
$('eta').set('html', '');
$('nb_connections').set('html', '');
$('total_downloaded').set('html', '');
$('total_uploaded').set('html', '');
$('dl_speed').set('html', '');
$('up_speed').set('html', '');
$('dl_limit').set('html', '');
$('up_limit').set('html', '');
$('total_wasted').set('html', '');
$('seeds').set('html', '');
$('peers').set('html', '');
$('share_ratio').set('html', '');
$('reannounce').set('html', '');
$('last_seen').set('html', '');
$('total_size').set('html', '');
$('pieces').set('html', '');
$('created_by').set('html', '');
$('addition_date').set('html', '');
$('completion_date').set('html', '');
$('creation_date').set('html', '');
$('torrent_hash').set('html', '');
$('save_path').set('html', '');
$('comment').set('html', '');
};
temp = "QBT_TR(%1 (%2 max))QBT_TR[CONTEXT=PropertiesWidget]"
.replace("%1", data.nb_connections)
.replace("%2", data.nb_connections_limit < 0 ? "∞" : data.nb_connections_limit);
$('nb_connections').set('html', temp);
temp = "QBT_TR(%1 (%2 this session))QBT_TR[CONTEXT=PropertiesWidget]"
.replace("%1", friendlyUnit(data.total_downloaded))
.replace("%2", friendlyUnit(data.total_downloaded_session));
$('total_downloaded').set('html', temp);
temp = "QBT_TR(%1 (%2 this session))QBT_TR[CONTEXT=PropertiesWidget]"
.replace("%1", friendlyUnit(data.total_uploaded))
.replace("%2", friendlyUnit(data.total_uploaded_session));
$('total_uploaded').set('html', temp);
temp = "QBT_TR(%1 (%2 avg.))QBT_TR[CONTEXT=PropertiesWidget]"
.replace("%1", friendlyUnit(data.dl_speed, true))
.replace("%2", friendlyUnit(data.dl_speed_avg, true));
$('dl_speed').set('html', temp);
temp = "QBT_TR(%1 (%2 avg.))QBT_TR[CONTEXT=PropertiesWidget]"
.replace("%1", friendlyUnit(data.up_speed, true))
.replace("%2", friendlyUnit(data.up_speed_avg, true));
$('up_speed').set('html', temp);
temp = (data.dl_limit == -1 ? "∞" : friendlyUnit(data.dl_limit, true));
$('dl_limit').set('html', temp);
temp = (data.up_limit == -1 ? "∞" : friendlyUnit(data.up_limit, true));
$('up_limit').set('html', temp);
$('total_wasted').set('html', friendlyUnit(data.total_wasted));
temp = "QBT_TR(%1 (%2 total))QBT_TR[CONTEXT=PropertiesWidget]"
.replace("%1", data.seeds)
.replace("%2", data.seeds_total);
$('seeds').set('html', temp);
temp = "QBT_TR(%1 (%2 total))QBT_TR[CONTEXT=PropertiesWidget]"
.replace("%1", data.peers)
.replace("%2", data.peers_total);
$('peers').set('html', temp);
$('share_ratio').set('html', data.share_ratio.toFixed(2));
$('reannounce').set('html', friendlyDuration(data.reannounce));
if (data.last_seen != -1)
temp = new Date(data.last_seen * 1000).toLocaleString();
else
temp = "QBT_TR(Never)QBT_TR[CONTEXT=PropertiesWidget]";
$('last_seen').set('html', temp);
$('total_size').set('html', friendlyUnit(data.total_size));
if (data.pieces_num != -1)
temp = "QBT_TR(%1 x %2 (have %3))QBT_TR[CONTEXT=PropertiesWidget]"
.replace("%1", data.pieces_num)
.replace("%2", friendlyUnit(data.piece_size))
.replace("%3", data.pieces_have);
else
temp = "QBT_TR(Unknown)QBT_TR[CONTEXT=HttpServer]";
$('pieces').set('html', temp);
$('created_by').set('html', escapeHtml(data.created_by));
if (data.addition_date != -1)
temp = new Date(data.addition_date * 1000).toLocaleString();
else
temp = "QBT_TR(Unknown)QBT_TR[CONTEXT=HttpServer]";
$('addition_date').set('html', temp);
if (data.completion_date != -1)
temp = new Date(data.completion_date * 1000).toLocaleString();
else
temp = "";
$('completion_date').set('html', temp);
if (data.creation_date != -1)
temp = new Date(data.creation_date * 1000).toLocaleString();
else
temp = "QBT_TR(Unknown)QBT_TR[CONTEXT=HttpServer]";
$('creation_date').set('html', temp);
$('save_path').set('html', data.save_path);
$('comment').set('html', parseHtmlLinks(escapeHtml(data.comment)));
}
else {
clearData();
}
let loadTorrentDataTimer;
const loadTorrentData = function() {
if ($('prop_general').hasClass('invisible')
|| $('propertiesPanel_collapseToggle').hasClass('panel-expand')) {
// Tab changed, don't do anything
return;
}
const current_hash = torrentsTable.getCurrentTorrentHash();
if (current_hash === "") {
clearData();
clearTimeout(loadTorrentDataTimer);
loadTorrentDataTimer = loadTorrentData.delay(5000);
return;
}
}).send();
};
// Display hash
$('torrent_hash').set('html', current_hash);
const url = new URI('api/v2/torrents/properties?hash=' + current_hash);
new Request.JSON({
url: url,
noCache: true,
method: 'get',
onFailure: function() {
$('error_div').set('html', 'QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]');
clearTimeout(loadTorrentDataTimer);
loadTorrentDataTimer = loadTorrentData.delay(10000);
},
onSuccess: function(data) {
$('error_div').set('html', '');
if (data) {
let temp;
// Update Torrent data
if (data.seeding_time > 0)
temp = "QBT_TR(%1 (%2 this session))QBT_TR[CONTEXT=PropertiesWidget]"
.replace("%1", window.qBittorrent.Misc.friendlyDuration(data.time_elapsed))
.replace("%2", window.qBittorrent.Misc.friendlyDuration(data.seeding_time));
else
temp = window.qBittorrent.Misc.friendlyDuration(data.time_elapsed);
$('time_elapsed').set('html', temp);
updateTorrentData = function() {
clearTimeout(loadTorrentDataTimer);
loadTorrentData();
};
$('eta').set('html', window.qBittorrent.Misc.friendlyDuration(data.eta));
temp = "QBT_TR(%1 (%2 max))QBT_TR[CONTEXT=PropertiesWidget]"
.replace("%1", data.nb_connections)
.replace("%2", data.nb_connections_limit < 0 ? "∞" : data.nb_connections_limit);
$('nb_connections').set('html', temp);
temp = "QBT_TR(%1 (%2 this session))QBT_TR[CONTEXT=PropertiesWidget]"
.replace("%1", window.qBittorrent.Misc.friendlyUnit(data.total_downloaded))
.replace("%2", window.qBittorrent.Misc.friendlyUnit(data.total_downloaded_session));
$('total_downloaded').set('html', temp);
temp = "QBT_TR(%1 (%2 this session))QBT_TR[CONTEXT=PropertiesWidget]"
.replace("%1", window.qBittorrent.Misc.friendlyUnit(data.total_uploaded))
.replace("%2", window.qBittorrent.Misc.friendlyUnit(data.total_uploaded_session));
$('total_uploaded').set('html', temp);
temp = "QBT_TR(%1 (%2 avg.))QBT_TR[CONTEXT=PropertiesWidget]"
.replace("%1", window.qBittorrent.Misc.friendlyUnit(data.dl_speed, true))
.replace("%2", window.qBittorrent.Misc.friendlyUnit(data.dl_speed_avg, true));
$('dl_speed').set('html', temp);
temp = "QBT_TR(%1 (%2 avg.))QBT_TR[CONTEXT=PropertiesWidget]"
.replace("%1", window.qBittorrent.Misc.friendlyUnit(data.up_speed, true))
.replace("%2", window.qBittorrent.Misc.friendlyUnit(data.up_speed_avg, true));
$('up_speed').set('html', temp);
temp = (data.dl_limit == -1 ? "∞" : window.qBittorrent.Misc.friendlyUnit(data.dl_limit, true));
$('dl_limit').set('html', temp);
temp = (data.up_limit == -1 ? "∞" : window.qBittorrent.Misc.friendlyUnit(data.up_limit, true));
$('up_limit').set('html', temp);
$('total_wasted').set('html', window.qBittorrent.Misc.friendlyUnit(data.total_wasted));
temp = "QBT_TR(%1 (%2 total))QBT_TR[CONTEXT=PropertiesWidget]"
.replace("%1", data.seeds)
.replace("%2", data.seeds_total);
$('seeds').set('html', temp);
temp = "QBT_TR(%1 (%2 total))QBT_TR[CONTEXT=PropertiesWidget]"
.replace("%1", data.peers)
.replace("%2", data.peers_total);
$('peers').set('html', temp);
$('share_ratio').set('html', data.share_ratio.toFixed(2));
$('reannounce').set('html', window.qBittorrent.Misc.friendlyDuration(data.reannounce));
if (data.last_seen != -1)
temp = new Date(data.last_seen * 1000).toLocaleString();
else
temp = "QBT_TR(Never)QBT_TR[CONTEXT=PropertiesWidget]";
$('last_seen').set('html', temp);
$('total_size').set('html', window.qBittorrent.Misc.friendlyUnit(data.total_size));
if (data.pieces_num != -1)
temp = "QBT_TR(%1 x %2 (have %3))QBT_TR[CONTEXT=PropertiesWidget]"
.replace("%1", data.pieces_num)
.replace("%2", window.qBittorrent.Misc.friendlyUnit(data.piece_size))
.replace("%3", data.pieces_have);
else
temp = "QBT_TR(Unknown)QBT_TR[CONTEXT=HttpServer]";
$('pieces').set('html', temp);
$('created_by').set('html', window.qBittorrent.Misc.escapeHtml(data.created_by));
if (data.addition_date != -1)
temp = new Date(data.addition_date * 1000).toLocaleString();
else
temp = "QBT_TR(Unknown)QBT_TR[CONTEXT=HttpServer]";
$('addition_date').set('html', temp);
if (data.completion_date != -1)
temp = new Date(data.completion_date * 1000).toLocaleString();
else
temp = "";
$('completion_date').set('html', temp);
if (data.creation_date != -1)
temp = new Date(data.creation_date * 1000).toLocaleString();
else
temp = "QBT_TR(Unknown)QBT_TR[CONTEXT=HttpServer]";
$('creation_date').set('html', temp);
$('save_path').set('html', data.save_path);
$('comment').set('html', window.qBittorrent.Misc.parseHtmlLinks(window.qBittorrent.Misc.escapeHtml(data.comment)));
}
else {
clearData();
}
clearTimeout(loadTorrentDataTimer);
loadTorrentDataTimer = loadTorrentData.delay(5000);
}
}).send();
};
const updateData = function() {
clearTimeout(loadTorrentDataTimer);
loadTorrentData();
};
return exports();
})();

View file

@ -28,144 +28,160 @@
'use strict';
let loadTorrentPeersTimer;
let syncTorrentPeersLastResponseId = 0;
let show_flags = true;
const loadTorrentPeersData = function() {
if ($('prop_peers').hasClass('invisible')
|| $('propertiesPanel_collapseToggle').hasClass('panel-expand')) {
syncTorrentPeersLastResponseId = 0;
torrentPeersTable.clear();
return;
}
const current_hash = torrentsTable.getCurrentTorrentHash();
if (current_hash === "") {
syncTorrentPeersLastResponseId = 0;
torrentPeersTable.clear();
clearTimeout(loadTorrentPeersTimer);
loadTorrentPeersTimer = loadTorrentPeersData.delay(getSyncMainDataInterval());
return;
}
const url = new URI('api/v2/sync/torrentPeers');
url.setData('rid', syncTorrentPeersLastResponseId);
url.setData('hash', current_hash);
new Request.JSON({
url: url,
noCache: true,
method: 'get',
onComplete: function() {
if (window.qBittorrent === undefined) {
window.qBittorrent = {};
}
window.qBittorrent.PropPeers = (function() {
const exports = function() {
return {
updateData: updateData
}
};
const torrentPeersTable = new window.qBittorrent.DynamicTable.TorrentPeersTable();
let loadTorrentPeersTimer;
let syncTorrentPeersLastResponseId = 0;
let show_flags = true;
const loadTorrentPeersData = function() {
if ($('prop_peers').hasClass('invisible')
|| $('propertiesPanel_collapseToggle').hasClass('panel-expand')) {
syncTorrentPeersLastResponseId = 0;
torrentPeersTable.clear();
return;
}
const current_hash = torrentsTable.getCurrentTorrentHash();
if (current_hash === "") {
syncTorrentPeersLastResponseId = 0;
torrentPeersTable.clear();
clearTimeout(loadTorrentPeersTimer);
loadTorrentPeersTimer = loadTorrentPeersData.delay(getSyncMainDataInterval());
},
onSuccess: function(response) {
$('error_div').set('html', '');
if (response) {
const full_update = (response['full_update'] === true);
if (full_update)
return;
}
const url = new URI('api/v2/sync/torrentPeers');
url.setData('rid', syncTorrentPeersLastResponseId);
url.setData('hash', current_hash);
new Request.JSON({
url: url,
noCache: true,
method: 'get',
onComplete: function() {
clearTimeout(loadTorrentPeersTimer);
loadTorrentPeersTimer = loadTorrentPeersData.delay(getSyncMainDataInterval());
},
onSuccess: function(response) {
$('error_div').set('html', '');
if (response) {
const full_update = (response['full_update'] === true);
if (full_update)
torrentPeersTable.clear();
if (response['rid'])
syncTorrentPeersLastResponseId = response['rid'];
if (response['peers']) {
for (const key in response['peers']) {
response['peers'][key]['rowId'] = key;
if (response['peers'][key]['client'])
response['peers'][key]['client'] = window.qBittorrent.Misc.escapeHtml(response['peers'][key]['client']);
torrentPeersTable.updateRowData(response['peers'][key]);
}
}
if (response['peers_removed']) {
response['peers_removed'].each(function(hash) {
torrentPeersTable.removeRow(hash);
});
}
torrentPeersTable.updateTable(full_update);
torrentPeersTable.altRow();
if (response['show_flags']) {
if (show_flags != response['show_flags']) {
show_flags = response['show_flags'];
torrentPeersTable.columns['country'].force_hide = !show_flags;
torrentPeersTable.updateColumn('country');
}
}
}
else {
torrentPeersTable.clear();
if (response['rid'])
syncTorrentPeersLastResponseId = response['rid'];
if (response['peers']) {
for (const key in response['peers']) {
response['peers'][key]['rowId'] = key;
if (response['peers'][key]['client'])
response['peers'][key]['client'] = escapeHtml(response['peers'][key]['client']);
torrentPeersTable.updateRowData(response['peers'][key]);
}
}
if (response['peers_removed']) {
response['peers_removed'].each(function(hash) {
torrentPeersTable.removeRow(hash);
});
}
torrentPeersTable.updateTable(full_update);
torrentPeersTable.altRow();
}
}).send();
};
if (response['show_flags']) {
if (show_flags != response['show_flags']) {
show_flags = response['show_flags'];
torrentPeersTable.columns['country'].force_hide = !show_flags;
torrentPeersTable.updateColumn('country');
}
const updateData = function() {
clearTimeout(loadTorrentPeersTimer);
loadTorrentPeersData();
};
const torrentPeersContextMenu = new window.qBittorrent.ContextMenu.ContextMenu({
targets: '#torrentPeersTableDiv',
menu: 'torrentPeersMenu',
actions: {
addPeer: function(element, ref) {
const hash = torrentsTable.getCurrentTorrentHash();
if (!hash)
return;
new MochaUI.Window({
id: 'addPeersPage',
title: "QBT_TR(Add Peers)QBT_TR[CONTEXT=PeersAdditionDialog]",
loadMethod: 'iframe',
contentURL: 'addpeers.html?hash=' + hash,
scrollbars: false,
resizable: false,
maximizable: false,
paddingVertical: 0,
paddingHorizontal: 0,
width: 350,
height: 240
});
},
banPeer: function(element, ref) {
const selectedPeers = torrentPeersTable.selectedRowsIds();
if (selectedPeers.length === 0)
return;
if (confirm('QBT_TR(Are you sure you want to permanently ban the selected peers?)QBT_TR[CONTEXT=PeerListWidget]')) {
new Request({
url: 'api/v2/torrents/banPeers',
noCache: true,
method: 'post',
data: {
hash: torrentsTable.getCurrentTorrentHash(),
peers: selectedPeers.join('|')
}
}).send();
}
}
},
offsets: {
x: -15,
y: 2
},
onShow: function() {
const selectedPeers = torrentPeersTable.selectedRowsIds();
if (selectedPeers.length >= 1) {
this.showItem('copyPeer');
this.showItem('banPeer');
}
else {
torrentPeersTable.clear();
this.hideItem('copyPeer');
this.hideItem('banPeer');
}
}
}).send();
};
});
updateTorrentPeersData = function() {
clearTimeout(loadTorrentPeersTimer);
loadTorrentPeersData();
};
const torrentPeersContextMenu = new ContextMenu({
targets: '#torrentPeersTableDiv',
menu: 'torrentPeersMenu',
actions: {
addPeer: function(element, ref) {
const hash = torrentsTable.getCurrentTorrentHash();
if (!hash)
return;
new MochaUI.Window({
id: 'addPeersPage',
title: "QBT_TR(Add Peers)QBT_TR[CONTEXT=PeersAdditionDialog]",
loadMethod: 'iframe',
contentURL: 'addpeers.html?hash=' + hash,
scrollbars: false,
resizable: false,
maximizable: false,
paddingVertical: 0,
paddingHorizontal: 0,
width: 350,
height: 240
});
},
banPeer: function(element, ref) {
const selectedPeers = torrentPeersTable.selectedRowsIds();
if (selectedPeers.length === 0)
return;
if (confirm('QBT_TR(Are you sure you want to permanently ban the selected peers?)QBT_TR[CONTEXT=PeerListWidget]')) {
new Request({
url: 'api/v2/torrents/banPeers',
noCache: true,
method: 'post',
data: {
hash: torrentsTable.getCurrentTorrentHash(),
peers: selectedPeers.join('|')
}
}).send();
}
new ClipboardJS('#CopyPeerInfo', {
text: function(trigger) {
return torrentPeersTable.selectedRowsIds().join("\n");
}
},
offsets: {
x: -15,
y: 2
},
onShow: function() {
const selectedPeers = torrentPeersTable.selectedRowsIds();
});
if (selectedPeers.length >= 1) {
this.showItem('copyPeer');
this.showItem('banPeer');
}
else {
this.hideItem('copyPeer');
this.hideItem('banPeer');
}
}
});
torrentPeersTable.setup('torrentPeersTableDiv', 'torrentPeersTableFixedHeaderDiv', torrentPeersContextMenu);
new ClipboardJS('#CopyPeerInfo', {
text: function(trigger) {
return torrentPeersTable.selectedRowsIds().join("\n");
}
});
torrentPeersTable.setup('torrentPeersTableDiv', 'torrentPeersTableFixedHeaderDiv', torrentPeersContextMenu);
return exports();
})();

View file

@ -28,195 +28,211 @@
'use strict';
this.current_hash = "";
if (window.qBittorrent === undefined) {
window.qBittorrent = {};
}
let loadTrackersDataTimer;
const loadTrackersData = function() {
if ($('prop_trackers').hasClass('invisible')
|| $('propertiesPanel_collapseToggle').hasClass('panel-expand')) {
// Tab changed, don't do anything
return;
}
const new_hash = torrentsTable.getCurrentTorrentHash();
if (new_hash === "") {
torrentTrackersTable.clear();
clearTimeout(loadTrackersDataTimer);
loadTrackersDataTimer = loadTrackersData.delay(10000);
return;
}
if (new_hash != current_hash) {
torrentTrackersTable.clear();
current_hash = new_hash;
}
const url = new URI('api/v2/torrents/trackers?hash=' + current_hash);
new Request.JSON({
url: url,
noCache: true,
method: 'get',
onComplete: function() {
window.qBittorrent.PropTrackers = (function() {
const exports = function() {
return {
updateData: updateData
};
};
let current_hash = "";
const torrentTrackersTable = new window.qBittorrent.DynamicTable.TorrentTrackersTable();
let loadTrackersDataTimer;
const loadTrackersData = function() {
if ($('prop_trackers').hasClass('invisible')
|| $('propertiesPanel_collapseToggle').hasClass('panel-expand')) {
// Tab changed, don't do anything
return;
}
const new_hash = torrentsTable.getCurrentTorrentHash();
if (new_hash === "") {
torrentTrackersTable.clear();
clearTimeout(loadTrackersDataTimer);
loadTrackersDataTimer = loadTrackersData.delay(10000);
},
onSuccess: function(trackers) {
const selectedTrackers = torrentTrackersTable.selectedRowsIds();
return;
}
if (new_hash != current_hash) {
torrentTrackersTable.clear();
current_hash = new_hash;
}
const url = new URI('api/v2/torrents/trackers?hash=' + current_hash);
new Request.JSON({
url: url,
noCache: true,
method: 'get',
onComplete: function() {
clearTimeout(loadTrackersDataTimer);
loadTrackersDataTimer = loadTrackersData.delay(10000);
},
onSuccess: function(trackers) {
const selectedTrackers = torrentTrackersTable.selectedRowsIds();
torrentTrackersTable.clear();
if (trackers) {
trackers.each(function(tracker) {
const url = escapeHtml(tracker.url);
let status;
switch (tracker.status) {
case 0:
status = "QBT_TR(Disabled)QBT_TR[CONTEXT=TrackerListWidget]";
break;
case 1:
status = "QBT_TR(Not contacted yet)QBT_TR[CONTEXT=TrackerListWidget]";
break;
case 2:
status = "QBT_TR(Working)QBT_TR[CONTEXT=TrackerListWidget]";
break;
case 3:
status = "QBT_TR(Updating...)QBT_TR[CONTEXT=TrackerListWidget]";
break;
case 4:
status = "QBT_TR(Not working)QBT_TR[CONTEXT=TrackerListWidget]";
break;
}
if (trackers) {
trackers.each(function(tracker) {
const url = window.qBittorrent.Misc.escapeHtml(tracker.url);
let status;
switch (tracker.status) {
case 0:
status = "QBT_TR(Disabled)QBT_TR[CONTEXT=TrackerListWidget]";
break;
case 1:
status = "QBT_TR(Not contacted yet)QBT_TR[CONTEXT=TrackerListWidget]";
break;
case 2:
status = "QBT_TR(Working)QBT_TR[CONTEXT=TrackerListWidget]";
break;
case 3:
status = "QBT_TR(Updating...)QBT_TR[CONTEXT=TrackerListWidget]";
break;
case 4:
status = "QBT_TR(Not working)QBT_TR[CONTEXT=TrackerListWidget]";
break;
}
const row = {
rowId: url,
tier: tracker.tier,
url: url,
status: status,
peers: tracker.num_peers,
seeds: (tracker.num_seeds >= 0) ? tracker.num_seeds : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
leeches: (tracker.num_leeches >= 0) ? tracker.num_leeches : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
downloaded: (tracker.num_downloaded >= 0) ? tracker.num_downloaded : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
message: escapeHtml(tracker.msg)
};
const row = {
rowId: url,
tier: tracker.tier,
url: url,
status: status,
peers: tracker.num_peers,
seeds: (tracker.num_seeds >= 0) ? tracker.num_seeds : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
leeches: (tracker.num_leeches >= 0) ? tracker.num_leeches : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
downloaded: (tracker.num_downloaded >= 0) ? tracker.num_downloaded : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
message: window.qBittorrent.Misc.escapeHtml(tracker.msg)
};
torrentTrackersTable.updateRowData(row);
});
torrentTrackersTable.updateRowData(row);
});
torrentTrackersTable.updateTable(false);
torrentTrackersTable.altRow();
torrentTrackersTable.updateTable(false);
torrentTrackersTable.altRow();
if (selectedTrackers.length > 0)
torrentTrackersTable.reselectRows(selectedTrackers);
if (selectedTrackers.length > 0)
torrentTrackersTable.reselectRows(selectedTrackers);
}
}
}).send();
};
const updateData = function() {
clearTimeout(loadTrackersDataTimer);
loadTrackersData();
};
const torrentTrackersContextMenu = new window.qBittorrent.ContextMenu.ContextMenu({
targets: '#torrentTrackersTableDiv',
menu: 'torrentTrackersMenu',
actions: {
AddTracker: function(element, ref) {
addTrackerFN();
},
EditTracker: function(element, ref) {
// only allow editing of one row
element.firstChild.click();
editTrackerFN(element);
},
RemoveTracker: function(element, ref) {
removeTrackerFN(element);
}
},
offsets: {
x: -15,
y: 2
},
onShow: function() {
const selectedTrackers = torrentTrackersTable.selectedRowsIds();
const containsStaticTracker = selectedTrackers.some(function(tracker) {
return (tracker.indexOf("** [") === 0);
});
if (containsStaticTracker || (selectedTrackers.length === 0)) {
this.hideItem('EditTracker');
this.hideItem('RemoveTracker');
this.hideItem('CopyTrackerUrl');
}
else {
this.showItem('EditTracker');
this.showItem('RemoveTracker');
this.showItem('CopyTrackerUrl');
}
}
}).send();
};
});
updateTrackersData = function() {
clearTimeout(loadTrackersDataTimer);
loadTrackersData();
};
const torrentTrackersContextMenu = new ContextMenu({
targets: '#torrentTrackersTableDiv',
menu: 'torrentTrackersMenu',
actions: {
AddTracker: function(element, ref) {
addTrackerFN();
},
EditTracker: function(element, ref) {
// only allow editing of one row
element.firstChild.click();
editTrackerFN(element);
},
RemoveTracker: function(element, ref) {
removeTrackerFN(element);
}
},
offsets: {
x: -15,
y: 2
},
onShow: function() {
const selectedTrackers = torrentTrackersTable.selectedRowsIds();
const containsStaticTracker = selectedTrackers.some(function(tracker) {
return (tracker.indexOf("** [") === 0);
const addTrackerFN = function() {
if (current_hash.length === 0) return;
new MochaUI.Window({
id: 'trackersPage',
title: "QBT_TR(Trackers addition dialog)QBT_TR[CONTEXT=TrackersAdditionDialog]",
loadMethod: 'iframe',
contentURL: 'addtrackers.html?hash=' + current_hash,
scrollbars: true,
resizable: false,
maximizable: false,
closable: true,
paddingVertical: 0,
paddingHorizontal: 0,
width: 500,
height: 250,
onCloseComplete: function() {
updateData();
}
});
};
if (containsStaticTracker || (selectedTrackers.length === 0)) {
this.hideItem('EditTracker');
this.hideItem('RemoveTracker');
this.hideItem('CopyTrackerUrl');
}
else {
this.showItem('EditTracker');
this.showItem('RemoveTracker');
this.showItem('CopyTrackerUrl');
}
}
});
const editTrackerFN = function(element) {
if (current_hash.length === 0) return;
const addTrackerFN = function() {
if (current_hash.length === 0) return;
new MochaUI.Window({
id: 'trackersPage',
title: "QBT_TR(Trackers addition dialog)QBT_TR[CONTEXT=TrackersAdditionDialog]",
loadMethod: 'iframe',
contentURL: 'addtrackers.html?hash=' + current_hash,
scrollbars: true,
resizable: false,
maximizable: false,
closable: true,
paddingVertical: 0,
paddingHorizontal: 0,
width: 500,
height: 250,
onCloseComplete: function() {
updateTrackersData();
const trackerUrl = encodeURIComponent(element.childNodes[1].innerText);
new MochaUI.Window({
id: 'trackersPage',
title: "QBT_TR(Tracker editing)QBT_TR[CONTEXT=TrackerListWidget]",
loadMethod: 'iframe',
contentURL: 'edittracker.html?hash=' + current_hash + '&url=' + trackerUrl,
scrollbars: true,
resizable: false,
maximizable: false,
closable: true,
paddingVertical: 0,
paddingHorizontal: 0,
width: 500,
height: 150,
onCloseComplete: function() {
updateData();
}
});
};
const removeTrackerFN = function(element) {
if (current_hash.length === 0) return;
const selectedTrackers = torrentTrackersTable.selectedRowsIds();
new Request({
url: 'api/v2/torrents/removeTrackers',
method: 'post',
data: {
hash: current_hash,
urls: selectedTrackers.join("|")
},
onSuccess: function() {
updateData();
}
}).send();
};
new ClipboardJS('#CopyTrackerUrl', {
text: function(trigger) {
return torrentTrackersTable.selectedRowsIds().join("\n");
}
});
};
const editTrackerFN = function(element) {
if (current_hash.length === 0) return;
torrentTrackersTable.setup('torrentTrackersTableDiv', 'torrentTrackersTableFixedHeaderDiv', torrentTrackersContextMenu);
const trackerUrl = encodeURIComponent(element.childNodes[1].innerText);
new MochaUI.Window({
id: 'trackersPage',
title: "QBT_TR(Tracker editing)QBT_TR[CONTEXT=TrackerListWidget]",
loadMethod: 'iframe',
contentURL: 'edittracker.html?hash=' + current_hash + '&url=' + trackerUrl,
scrollbars: true,
resizable: false,
maximizable: false,
closable: true,
paddingVertical: 0,
paddingHorizontal: 0,
width: 500,
height: 150,
onCloseComplete: function() {
updateTrackersData();
}
});
};
const removeTrackerFN = function(element) {
if (current_hash.length === 0) return;
const selectedTrackers = torrentTrackersTable.selectedRowsIds();
new Request({
url: 'api/v2/torrents/removeTrackers',
method: 'post',
data: {
hash: current_hash,
urls: selectedTrackers.join("|")
},
onSuccess: function() {
updateTrackersData();
}
}).send();
};
new ClipboardJS('#CopyTrackerUrl', {
text: function(trigger) {
return torrentTrackersTable.selectedRowsIds().join("\n");
}
});
torrentTrackersTable.setup('torrentTrackersTableDiv', 'torrentTrackersTableFixedHeaderDiv', torrentTrackersContextMenu);
return exports();
})();

View file

@ -28,112 +28,126 @@
'use strict';
const webseedsDynTable = new Class({
if (window.qBittorrent === undefined) {
window.qBittorrent = {};
}
initialize: function() {},
window.qBittorrent.PropWebseeds = (function() {
const exports = function() {
return {
updateData: updateData
};
};
setup: function(table) {
this.table = $(table);
this.rows = new Hash();
},
const webseedsDynTable = new Class({
removeRow: function(url) {
if (this.rows.has(url)) {
const tr = this.rows.get(url);
tr.dispose();
this.rows.erase(url);
initialize: function() {},
setup: function(table) {
this.table = $(table);
this.rows = new Hash();
},
removeRow: function(url) {
if (this.rows.has(url)) {
const tr = this.rows.get(url);
tr.dispose();
this.rows.erase(url);
return true;
}
return false;
},
removeAllRows: function() {
this.rows.each(function(tr, url) {
this.removeRow(url);
}.bind(this));
},
updateRow: function(tr, row) {
const tds = tr.getElements('td');
for (let i = 0; i < row.length; ++i) {
tds[i].set('html', row[i]);
}
return true;
}
return false;
},
},
removeAllRows: function() {
this.rows.each(function(tr, url) {
this.removeRow(url);
}.bind(this));
},
insertRow: function(row) {
const url = row[0];
if (this.rows.has(url)) {
const tableRow = this.rows.get(url);
this.updateRow(tableRow, row);
return;
}
//this.removeRow(id);
const tr = new Element('tr');
this.rows.set(url, tr);
for (let i = 0; i < row.length; ++i) {
const td = new Element('td');
td.set('html', row[i]);
td.injectInside(tr);
}
tr.injectInside(this.table);
},
});
updateRow: function(tr, row) {
const tds = tr.getElements('td');
for (let i = 0; i < row.length; ++i) {
tds[i].set('html', row[i]);
}
return true;
},
let current_hash = "";
insertRow: function(row) {
const url = row[0];
if (this.rows.has(url)) {
const tableRow = this.rows.get(url);
this.updateRow(tableRow, row);
let loadWebSeedsDataTimer;
const loadWebSeedsData = function() {
if ($('prop_webseeds').hasClass('invisible')
|| $('propertiesPanel_collapseToggle').hasClass('panel-expand')) {
// Tab changed, don't do anything
return;
}
//this.removeRow(id);
const tr = new Element('tr');
this.rows.set(url, tr);
for (let i = 0; i < row.length; ++i) {
const td = new Element('td');
td.set('html', row[i]);
td.injectInside(tr);
}
tr.injectInside(this.table);
},
});
this.current_hash = "";
let loadWebSeedsDataTimer;
const loadWebSeedsData = function() {
if ($('prop_webseeds').hasClass('invisible')
|| $('propertiesPanel_collapseToggle').hasClass('panel-expand')) {
// Tab changed, don't do anything
return;
}
const new_hash = torrentsTable.getCurrentTorrentHash();
if (new_hash === "") {
wsTable.removeAllRows();
clearTimeout(loadWebSeedsDataTimer);
loadWebSeedsDataTimer = loadWebSeedsData.delay(10000);
return;
}
if (new_hash != current_hash) {
wsTable.removeAllRows();
current_hash = new_hash;
}
const url = new URI('api/v2/torrents/webseeds?hash=' + current_hash);
new Request.JSON({
url: url,
noCache: true,
method: 'get',
onFailure: function() {
$('error_div').set('html', 'QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]');
clearTimeout(loadWebSeedsDataTimer);
loadWebSeedsDataTimer = loadWebSeedsData.delay(20000);
},
onSuccess: function(webseeds) {
$('error_div').set('html', '');
if (webseeds) {
// Update WebSeeds data
webseeds.each(function(webseed) {
const row = [];
row.length = 1;
row[0] = webseed.url;
wsTable.insertRow(row);
});
}
else {
wsTable.removeAllRows();
}
const new_hash = torrentsTable.getCurrentTorrentHash();
if (new_hash === "") {
wsTable.removeAllRows();
clearTimeout(loadWebSeedsDataTimer);
loadWebSeedsDataTimer = loadWebSeedsData.delay(10000);
return;
}
}).send();
};
if (new_hash != current_hash) {
wsTable.removeAllRows();
current_hash = new_hash;
}
const url = new URI('api/v2/torrents/webseeds?hash=' + current_hash);
new Request.JSON({
url: url,
noCache: true,
method: 'get',
onFailure: function() {
$('error_div').set('html', 'QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]');
clearTimeout(loadWebSeedsDataTimer);
loadWebSeedsDataTimer = loadWebSeedsData.delay(20000);
},
onSuccess: function(webseeds) {
$('error_div').set('html', '');
if (webseeds) {
// Update WebSeeds data
webseeds.each(function(webseed) {
const row = [];
row.length = 1;
row[0] = webseed.url;
wsTable.insertRow(row);
});
}
else {
wsTable.removeAllRows();
}
clearTimeout(loadWebSeedsDataTimer);
loadWebSeedsDataTimer = loadWebSeedsData.delay(10000);
}
}).send();
};
updateWebSeedsData = function() {
clearTimeout(loadWebSeedsDataTimer);
loadWebSeedsData();
};
const updateData = function() {
clearTimeout(loadWebSeedsDataTimer);
loadWebSeedsData();
};
const wsTable = new webseedsDynTable();
wsTable.setup($('webseedsTable'));
const wsTable = new webseedsDynTable();
wsTable.setup($('webseedsTable'));
return exports();
})();

View file

@ -33,7 +33,7 @@
const path = new URI().getData('path');
// set text field to current value
if (path)
$('setLocation').value = escapeHtml(decodeURIComponent(path));
$('setLocation').value = window.qBittorrent.Misc.escapeHtml(decodeURIComponent(path));
$('setLocation').focus();
$('setLocationButton').addEvent('click', function(e) {

View file

@ -37,9 +37,9 @@
const origValues = new URI().getData('orig').split('|');
const values = {
ratioLimit: friendlyFloat(origValues[0], 2),
ratioLimit: window.qBittorrent.Misc.friendlyFloat(origValues[0], 2),
seedingTimeLimit: parseInt(origValues[1]),
maxRatio: friendlyFloat(origValues[2], 2),
maxRatio: window.qBittorrent.Misc.friendlyFloat(origValues[2], 2),
maxSeedingTime: parseInt(origValues[3])
};

View file

@ -23,7 +23,7 @@
<label for="autoTMM">QBT_TR(Torrent Management Mode:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
</td>
<td>
<select id="autoTMM" name="autoTMM" onchange="changeTMM(this)">
<select id="autoTMM" name="autoTMM" onchange="qBittorrent.Download.changeTMM(this)">
<option selected value="false">Manual</option>
<option value="true">Automatic</option>
</select>
@ -51,7 +51,7 @@
</td>
<td>
<div class="select-watched-folder-editable">
<select id="categorySelect" onchange="changeCategorySelect(this)">
<select id="categorySelect" onchange="qBittorrent.Download.changeCategorySelect(this)">
<option selected value="\other"></option>
</select>
<input name="category" type="text" value="" />

View file

@ -681,22 +681,24 @@
<script>
'use strict';
$('qbittorrentVersion').innerText = ("qBittorrent " + qbtVersion()
(function() {
$('qbittorrentVersion').innerText = ("qBittorrent " + qbtVersion()
+ " QBT_TR(Web UI)QBT_TR[CONTEXT=OptionsDialog]");
new Request.JSON({
url: 'api/v2/app/buildInfo',
method: 'get',
noCache: true,
onSuccess: function(info) {
if (!info) return;
new Request.JSON({
url: 'api/v2/app/buildInfo',
method: 'get',
noCache: true,
onSuccess: function(info) {
if (!info) return;
$('qtVersion').textContent = info.qt;
$('libtorrentVersion').textContent = info.libtorrent;
$('boostVersion').textContent = info.boost;
$('opensslVersion').textContent = info.openssl;
$('zlibVersion').textContent = info.zlib;
$('qbittorrentVersion').textContent += " (" + info.bitness + "-bit)";
}
}).send();
$('qtVersion').textContent = info.qt;
$('libtorrentVersion').textContent = info.libtorrent;
$('boostVersion').textContent = info.boost;
$('opensslVersion').textContent = info.openssl;
$('zlibVersion').textContent = info.zlib;
$('qbittorrentVersion').textContent += " (" + info.bitness + "-bit)";
}
}).send();
})();
</script>

View file

@ -13,35 +13,37 @@
<script>
'use strict';
MochaUI.initializeTabs('aboutTabs');
(function() {
MochaUI.initializeTabs('aboutTabs');
$('aboutAboutLink').addEvent('click', function() {
$$('.aboutTabContent').addClass('invisible');
$('aboutAboutContent').removeClass('invisible');
});
$('aboutAboutLink').addEvent('click', function() {
$$('.aboutTabContent').addClass('invisible');
$('aboutAboutContent').removeClass('invisible');
});
$('aboutAuthorLink').addEvent('click', function() {
$$('.aboutTabContent').addClass('invisible');
$('aboutAuthorContent').removeClass('invisible');
});
$('aboutAuthorLink').addEvent('click', function() {
$$('.aboutTabContent').addClass('invisible');
$('aboutAuthorContent').removeClass('invisible');
});
$('aboutSpecialThanksLink').addEvent('click', function() {
$$('.aboutTabContent').addClass('invisible');
$('aboutSpecialThanksContent').removeClass('invisible');
});
$('aboutSpecialThanksLink').addEvent('click', function() {
$$('.aboutTabContent').addClass('invisible');
$('aboutSpecialThanksContent').removeClass('invisible');
});
$('aboutTranslatorsLink').addEvent('click', function() {
$$('.aboutTabContent').addClass('invisible');
$('aboutTranslatorsContent').removeClass('invisible');
});
$('aboutTranslatorsLink').addEvent('click', function() {
$$('.aboutTabContent').addClass('invisible');
$('aboutTranslatorsContent').removeClass('invisible');
});
$('aboutLicenseLink').addEvent('click', function() {
$$('.aboutTabContent').addClass('invisible');
$('aboutLicenseContent').removeClass('invisible');
});
$('aboutLicenseLink').addEvent('click', function() {
$$('.aboutTabContent').addClass('invisible');
$('aboutLicenseContent').removeClass('invisible');
});
$('aboutLibrariesLink').addEvent('click', function() {
$$('.aboutTabContent').addClass('invisible');
$('aboutLibrariesContent').removeClass('invisible');
});
$('aboutLibrariesLink').addEvent('click', function() {
$$('.aboutTabContent').addClass('invisible');
$('aboutLibrariesContent').removeClass('invisible');
});
})();
</script>

View file

@ -32,79 +32,94 @@
<script>
'use strict';
const categoriesFilterContextMenu = new CategoriesFilterContextMenu({
targets: '.categoriesFilterContextMenuTarget',
menu: 'categoriesFilterMenu',
actions: {
createCategory: function(element, ref) {
createCategoryFN();
if (window.qBittorrent === undefined) {
window.qBittorrent = {};
}
window.qBittorrent.Filters = (function() {
const exports = function() {
return {
categoriesFilterContextMenu: categoriesFilterContextMenu,
tagsFilterContextMenu: tagsFilterContextMenu
};
};
const categoriesFilterContextMenu = new window.qBittorrent.ContextMenu.CategoriesFilterContextMenu({
targets: '.categoriesFilterContextMenuTarget',
menu: 'categoriesFilterMenu',
actions: {
createCategory: function(element, ref) {
createCategoryFN();
},
editCategory: function(element, ref) {
editCategoryFN(element.id);
},
deleteCategory: function(element, ref) {
removeCategoryFN(element.id);
},
deleteUnusedCategories: function(element, ref) {
deleteUnusedCategoriesFN();
},
startTorrentsByCategory: function(element, ref) {
startTorrentsByCategoryFN(element.id);
},
pauseTorrentsByCategory: function(element, ref) {
pauseTorrentsByCategoryFN(element.id);
},
deleteTorrentsByCategory: function(element, ref) {
deleteTorrentsByCategoryFN(element.id);
}
},
editCategory: function(element, ref) {
editCategoryFN(element.id);
offsets: {
x: -15,
y: 2
},
deleteCategory: function(element, ref) {
removeCategoryFN(element.id);
},
deleteUnusedCategories: function(element, ref) {
deleteUnusedCategoriesFN();
},
startTorrentsByCategory: function(element, ref) {
startTorrentsByCategoryFN(element.id);
},
pauseTorrentsByCategory: function(element, ref) {
pauseTorrentsByCategoryFN(element.id);
},
deleteTorrentsByCategory: function(element, ref) {
deleteTorrentsByCategoryFN(element.id);
onShow: function() {
this.options.element.firstChild.click();
}
},
offsets: {
x: -15,
y: 2
},
onShow: function() {
this.options.element.firstChild.click();
}
});
});
const tagsFilterContextMenu = new TagsFilterContextMenu({
targets: '.tagsFilterContextMenuTarget',
menu: 'tagsFilterMenu',
actions: {
createTag: function(element, ref) {
createTagFN();
const tagsFilterContextMenu = new window.qBittorrent.ContextMenu.TagsFilterContextMenu({
targets: '.tagsFilterContextMenuTarget',
menu: 'tagsFilterMenu',
actions: {
createTag: function(element, ref) {
createTagFN();
},
deleteTag: function(element, ref) {
removeTagFN(element.id);
},
deleteUnusedTags: function(element, ref) {
deleteUnusedTagsFN();
},
startTorrentsByTag: function(element, ref) {
startTorrentsByTagFN(element.id);
},
pauseTorrentsByTag: function(element, ref) {
pauseTorrentsByTagFN(element.id);
},
deleteTorrentsByTag: function(element, ref) {
deleteTorrentsByTagFN(element.id);
}
},
deleteTag: function(element, ref) {
removeTagFN(element.id);
offsets: {
x: -15,
y: 2
},
deleteUnusedTags: function(element, ref) {
deleteUnusedTagsFN();
},
startTorrentsByTag: function(element, ref) {
startTorrentsByTagFN(element.id);
},
pauseTorrentsByTag: function(element, ref) {
pauseTorrentsByTagFN(element.id);
},
deleteTorrentsByTag: function(element, ref) {
deleteTorrentsByTagFN(element.id);
onShow: function() {
this.options.element.firstChild.click();
}
},
offsets: {
x: -15,
y: 2
},
onShow: function() {
this.options.element.firstChild.click();
}
});
});
if (LocalPreferences.get('filter_status_collapsed') === "true")
toggleFilterDisplay('status');
if (LocalPreferences.get('filter_status_collapsed') === "true")
toggleFilterDisplay('status');
if (LocalPreferences.get('filter_category_collapsed') === "true")
toggleFilterDisplay('category');
if (LocalPreferences.get('filter_category_collapsed') === "true")
toggleFilterDisplay('category');
if (LocalPreferences.get('filter_tag_collapsed') === "true")
toggleFilterDisplay('tag');
if (LocalPreferences.get('filter_tag_collapsed') === "true")
toggleFilterDisplay('tag');
return exports();
})();
</script>

View file

@ -20,8 +20,8 @@
<div>
<input type="text" id="newPluginPath" placeholder="QBT_TR(URL or local directory)QBT_TR[CONTEXT=PluginSourceDlg]" autocorrect="off" autocapitalize="none" />
<div style="margin-top: 10px; text-align: center;">
<button id="newPluginCancel" onclick="closeSearchWindow('installSearchPlugin');">QBT_TR(Cancel)QBT_TR[CONTEXT=PluginSourceDlg]</button>
<button id="newPluginOk" onclick="newPluginOk();">QBT_TR(Ok)QBT_TR[CONTEXT=PluginSourceDlg]</button>
<button id="newPluginCancel" onclick="qBittorrent.SearchPlugins.closeSearchWindow('installSearchPlugin');">QBT_TR(Cancel)QBT_TR[CONTEXT=PluginSourceDlg]</button>
<button id="newPluginOk" onclick="qBittorrent.InstallSearchPlugin.newPluginOk();">QBT_TR(Ok)QBT_TR[CONTEXT=PluginSourceDlg]</button>
</div>
</div>
</div>
@ -29,41 +29,55 @@
<script>
'use strict';
this.initInstallSearchPlugin = function() {
new Keyboard({
defaultEventType: 'keydown',
events: {
'Enter': function(e) {
// accept enter key as a click
new Event(e).stop();
if (window.qBittorrent === undefined) {
window.qBittorrent = {};
}
const elem = e.event.srcElement;
if ((elem.id === "newPluginPath") || (elem.id === "newPluginOk"))
newPluginOk();
else if (elem.id === "newPluginCancel")
closeSearchWindow('installSearchPlugin');
window.qBittorrent.InstallSearchPlugin = (function() {
const exports = function() {
return {
newPluginOk: newPluginOk
};
};
const init = function() {
new Keyboard({
defaultEventType: 'keydown',
events: {
'Enter': function(e) {
// accept enter key as a click
new Event(e).stop();
const elem = e.event.srcElement;
if ((elem.id === "newPluginPath") || (elem.id === "newPluginOk"))
newPluginOk();
else if (elem.id === "newPluginCancel")
window.qBittorrent.SearchPlugins.closeSearchWindow('installSearchPlugin');
}
}
}
}).activate();
}).activate();
$('newPluginPath').select();
};
$('newPluginPath').select();
};
this.newPluginOk = function() {
const path = $("newPluginPath").get("value").trim();
if (path)
new Request({
url: 'api/v2/search/installPlugin',
noCache: true,
method: 'post',
data: {
sources: path,
},
onRequest: function() {
closeSearchWindow('installSearchPlugin');
}
}).send();
};
const newPluginOk = function() {
const path = $("newPluginPath").get("value").trim();
if (path)
new Request({
url: 'api/v2/search/installPlugin',
noCache: true,
method: 'post',
data: {
sources: path,
},
onRequest: function() {
window.qBittorrent.SearchPlugins.closeSearchWindow('installSearchPlugin');
}
}).send();
};
initInstallSearchPlugin();
init();
return exports();
})();
</script>

File diff suppressed because it is too large Load diff

View file

@ -14,31 +14,33 @@
<script>
'use strict';
// Tabs
MochaUI.initializeTabs('preferencesTabs');
(function() {
// Tabs
MochaUI.initializeTabs('preferencesTabs');
$('PrefDownloadsLink').addEvent('click', function(e) {
$$('.PrefTab').addClass('invisible');
$('DownloadsTab').removeClass('invisible');
});
$('PrefConnectionLink').addEvent('click', function(e) {
$$('.PrefTab').addClass('invisible');
$('ConnectionTab').removeClass('invisible');
});
$('PrefSpeedLink').addEvent('click', function(e) {
$$('.PrefTab').addClass('invisible');
$('SpeedTab').removeClass('invisible');
});
$('PrefBittorrentLink').addEvent('click', function(e) {
$$('.PrefTab').addClass('invisible');
$('BittorrentTab').removeClass('invisible');
});
$('PrefWebUILink').addEvent('click', function(e) {
$$('.PrefTab').addClass('invisible');
$('WebUITab').removeClass('invisible');
});
$('PrefAdvancedLink').addEvent('click', function(e) {
$$('.PrefTab').addClass('invisible');
$('AdvancedTab').removeClass('invisible');
});
$('PrefDownloadsLink').addEvent('click', function(e) {
$$('.PrefTab').addClass('invisible');
$('DownloadsTab').removeClass('invisible');
});
$('PrefConnectionLink').addEvent('click', function(e) {
$$('.PrefTab').addClass('invisible');
$('ConnectionTab').removeClass('invisible');
});
$('PrefSpeedLink').addEvent('click', function(e) {
$$('.PrefTab').addClass('invisible');
$('SpeedTab').removeClass('invisible');
});
$('PrefBittorrentLink').addEvent('click', function(e) {
$$('.PrefTab').addClass('invisible');
$('BittorrentTab').removeClass('invisible');
});
$('PrefWebUILink').addEvent('click', function(e) {
$$('.PrefTab').addClass('invisible');
$('WebUITab').removeClass('invisible');
});
$('PrefAdvancedLink').addEvent('click', function(e) {
$$('.PrefTab').addClass('invisible');
$('AdvancedTab').removeClass('invisible');
});
})();
</script>

View file

@ -155,7 +155,9 @@
<script>
'use strict';
const selectedTab = $(LocalPreferences.get('selected_tab', 'PropGeneralLink'));
if (selectedTab)
selectedTab.click();
(function() {
const selectedTab = $(LocalPreferences.get('selected_tab', 'PropGeneralLink'));
if (selectedTab)
selectedTab.click();
})();
</script>

File diff suppressed because it is too large Load diff

View file

@ -65,9 +65,9 @@
<span>QBT_TR(Warning: Be sure to comply with your country's copyright laws when downloading torrents from any of these search engines.)QBT_TR[CONTEXT=PluginSelectDlg]</span>
<span style="font-style: italic;">QBT_TR(You can get new search engine plugins here:)QBT_TR[CONTEXT=PluginSelectDlg] <a href="http://plugins.qbittorrent.org" target="_blank">http://plugins.qbittorrent.org</a></span>
<div style="width: 100%; margin-top: 10px;">
<button style="width: 33%; line-height: 1.4em;" onclick="installPlugin();">QBT_TR(Install new plugin)QBT_TR[CONTEXT=PluginSelectDlg]</button>
<button style="width: 33%; line-height: 1.4em;" onclick="checkForUpdates();">QBT_TR(Check for updates)QBT_TR[CONTEXT=PluginSelectDlg]</button>
<button style="width: 32%; line-height: 1.4em;" onclick="closeSearchWindow('searchPlugins');">QBT_TR(Close)QBT_TR[CONTEXT=PluginSelectDlg]</button>
<button style="width: 33%; line-height: 1.4em;" onclick="qBittorrent.SearchPlugins.installPlugin();">QBT_TR(Install new plugin)QBT_TR[CONTEXT=PluginSelectDlg]</button>
<button style="width: 33%; line-height: 1.4em;" onclick="qBittorrent.SearchPlugins.checkForUpdates();">QBT_TR(Check for updates)QBT_TR[CONTEXT=PluginSelectDlg]</button>
<button style="width: 32%; line-height: 1.4em;" onclick="qBittorrent.SearchPlugins.closeSearchWindow('searchPlugins');">QBT_TR(Close)QBT_TR[CONTEXT=PluginSelectDlg]</button>
</div>
</div>
@ -79,142 +79,161 @@
<script>
'use strict';
this.searchPluginsTableContextMenu = undefined;
this.prevOffsetLeft = undefined;
this.prevOffsetTop = undefined;
if (window.qBittorrent === undefined) {
window.qBittorrent = {};
}
this.initSearchPlugins = function() {
searchPluginsTableContextMenu = new SearchPluginsTableContextMenu({
targets: '.searchPluginsTableRow',
menu: 'searchPluginsTableMenu',
actions: {
Enabled: enablePlugin,
Uninstall: uninstallPlugin
},
offsets: calculateContextMenuOffsets()
});
searchPluginsTable.setup('searchPluginsTableDiv', 'searchPluginsTableFixedHeaderDiv', searchPluginsTableContextMenu);
updateSearchPluginsTable();
};
this.closeSearchWindow = function(id) {
window.parent.MochaUI.closeWindow(window.parent.$(id));
};
this.installPlugin = function(path) {
new MochaUI.Window({
id: 'installSearchPlugin',
title: "QBT_TR(Install plugin)QBT_TR[CONTEXT=PluginSourceDlg]",
loadMethod: 'xhr',
contentURL: 'views/installsearchplugin.html',
scrollbars: false,
resizable: false,
maximizable: false,
paddingVertical: 0,
paddingHorizontal: 0,
width: 500,
height: 120
});
};
this.uninstallPlugin = function() {
const plugins = searchPluginsTable.selectedRowsIds().join('|');
const url = new URI('api/v2/search/uninstallPlugin');
new Request({
url: url,
noCache: true,
method: 'post',
data: {
names: plugins,
}
}).send();
};
this.enablePlugin = function() {
const plugins = searchPluginsTable.selectedRowsIds();
let enable = true;
if (plugins && plugins.length)
enable = !getPlugin(plugins[0]).enabled;
const url = new URI('api/v2/search/enablePlugin');
new Request({
url: url,
noCache: true,
method: 'post',
data: {
names: plugins.join('|'),
enable: enable
}
}).send();
};
this.checkForUpdates = function() {
const url = new URI('api/v2/search/updatePlugins');
new Request({
url: url,
noCache: true,
method: 'post'
}).send();
};
this.calculateContextMenuOffsets = function() {
prevOffsetLeft = document.getElementById("searchPlugins").getBoundingClientRect().left;
prevOffsetTop = document.getElementById("searchPlugins").getBoundingClientRect().top;
return {
x: -(prevOffsetLeft + 20),
y: -(prevOffsetTop + 2)
window.qBittorrent.SearchPlugins = (function() {
const exports = function() {
return {
closeSearchWindow: closeSearchWindow,
installPlugin: installPlugin,
checkForUpdates: checkForUpdates,
updateTable: updateTable
};
};
};
this.updateSearchPluginsTableContextMenuOffset = function() {
// only re-calculate if window has moved
if ((prevOffsetLeft !== document.getElementById("searchPlugins").getBoundingClientRect().left) || (prevOffsetTop !== document.getElementById("searchPlugins").getBoundingClientRect().top))
searchPluginsTableContextMenu.options.offsets = calculateContextMenuOffsets();
};
let searchPluginsTable;
let searchPluginsTableContextMenu;
let prevOffsetLeft;
let prevOffsetTop;
this.setupSearchPluginTableEvents = function(enable) {
if (enable)
$$(".searchPluginsTableRow").each(function(target) {
target.addEventListener('dblclick', enablePlugin, false);
target.addEventListener('contextmenu', updateSearchPluginsTableContextMenuOffset, true);
const initSearchPlugins = function() {
searchPluginsTable = new window.qBittorrent.DynamicTable.SearchPluginsTable();
searchPluginsTableContextMenu = new window.qBittorrent.ContextMenu.SearchPluginsTableContextMenu({
targets: '.searchPluginsTableRow',
menu: 'searchPluginsTableMenu',
actions: {
Enabled: enablePlugin,
Uninstall: uninstallPlugin
},
offsets: calculateContextMenuOffsets()
});
else
$$(".searchPluginsTableRow").each(function(target) {
target.removeEventListener('dblclick', enablePlugin, false);
target.removeEventListener('contextmenu', updateSearchPluginsTableContextMenuOffset, true);
searchPluginsTable.setup('searchPluginsTableDiv', 'searchPluginsTableFixedHeaderDiv', searchPluginsTableContextMenu);
updateTable();
};
const closeSearchWindow = function(id) {
window.parent.MochaUI.closeWindow(window.parent.$(id));
};
const installPlugin = function(path) {
new MochaUI.Window({
id: 'installSearchPlugin',
title: "QBT_TR(Install plugin)QBT_TR[CONTEXT=PluginSourceDlg]",
loadMethod: 'xhr',
contentURL: 'views/installsearchplugin.html',
scrollbars: false,
resizable: false,
maximizable: false,
paddingVertical: 0,
paddingHorizontal: 0,
width: 500,
height: 120
});
};
};
this.updateSearchPluginsTable = function() {
// clear event listeners
setupSearchPluginTableEvents(false);
const oldPlugins = Object.keys(searchPluginsTable.rows);
// remove old rows from the table
for (let i = 0; i < oldPlugins.length; ++i) {
let found = false;
for (let j = 0; j < searchPlugins.length; ++j) {
if (searchPlugins[j].name === oldPlugins[i]) {
found = true;
break;
const uninstallPlugin = function() {
const plugins = searchPluginsTable.selectedRowsIds().join('|');
const url = new URI('api/v2/search/uninstallPlugin');
new Request({
url: url,
noCache: true,
method: 'post',
data: {
names: plugins,
}
}).send();
};
const enablePlugin = function() {
const plugins = searchPluginsTable.selectedRowsIds();
let enable = true;
if (plugins && plugins.length)
enable = !window.qBittorrent.Search.getPlugin(plugins[0]).enabled;
const url = new URI('api/v2/search/enablePlugin');
new Request({
url: url,
noCache: true,
method: 'post',
data: {
names: plugins.join('|'),
enable: enable
}
}).send();
};
const checkForUpdates = function() {
const url = new URI('api/v2/search/updatePlugins');
new Request({
url: url,
noCache: true,
method: 'post'
}).send();
};
const calculateContextMenuOffsets = function() {
prevOffsetLeft = document.getElementById("searchPlugins").getBoundingClientRect().left;
prevOffsetTop = document.getElementById("searchPlugins").getBoundingClientRect().top;
return {
x: -(prevOffsetLeft + 20),
y: -(prevOffsetTop + 2)
};
};
const updateSearchPluginsTableContextMenuOffset = function() {
// only re-calculate if window has moved
if ((prevOffsetLeft !== document.getElementById("searchPlugins").getBoundingClientRect().left) || (prevOffsetTop !== document.getElementById("searchPlugins").getBoundingClientRect().top))
searchPluginsTableContextMenu.options.offsets = calculateContextMenuOffsets();
};
const setupSearchPluginTableEvents = function(enable) {
if (enable)
$$(".searchPluginsTableRow").each(function(target) {
target.addEventListener('dblclick', enablePlugin, false);
target.addEventListener('contextmenu', updateSearchPluginsTableContextMenuOffset, true);
});
else
$$(".searchPluginsTableRow").each(function(target) {
target.removeEventListener('dblclick', enablePlugin, false);
target.removeEventListener('contextmenu', updateSearchPluginsTableContextMenuOffset, true);
});
};
const updateTable = function() {
// clear event listeners
setupSearchPluginTableEvents(false);
const oldPlugins = Object.keys(searchPluginsTable.rows);
// remove old rows from the table
for (let i = 0; i < oldPlugins.length; ++i) {
let found = false;
for (let j = 0; j < window.qBittorrent.Search.searchPlugins.length; ++j) {
if (window.qBittorrent.Search.searchPlugins[j].name === oldPlugins[i]) {
found = true;
break;
}
}
if (!found)
searchPluginsTable.removeRow(oldPlugins[i]);
}
if (!found)
searchPluginsTable.removeRow(oldPlugins[i]);
}
for (let i = 0; i < searchPlugins.length; ++i) {
searchPlugins[i].rowId = searchPlugins[i].name;
searchPluginsTable.updateRowData(searchPlugins[i]);
}
for (let i = 0; i < window.qBittorrent.Search.searchPlugins.length; ++i) {
window.qBittorrent.Search.searchPlugins[i].rowId = window.qBittorrent.Search.searchPlugins[i].name;
searchPluginsTable.updateRowData(window.qBittorrent.Search.searchPlugins[i]);
}
searchPluginsTable.updateTable();
searchPluginsTable.altRow();
searchPluginsTable.updateTable();
searchPluginsTable.altRow();
// add event listeners
setupSearchPluginTableEvents(true);
};
// add event listeners
setupSearchPluginTableEvents(true);
};
initSearchPlugins();
initSearchPlugins();
return exports();
})();
</script>

View file

@ -18,81 +18,95 @@
<script>
'use strict';
//create a context menu
const torrentsTableContextMenu = new TorrentsTableContextMenu({
targets: '.torrentsTableContextMenuTarget',
menu: 'torrentsTableMenu',
actions: {
start: function(element, ref) {
startFN();
},
pause: function(element, ref) {
pauseFN();
},
forceStart: function(element, ref) {
setForceStartFN();
},
if (window.qBittorrent === undefined) {
window.qBittorrent = {};
}
delete: function(element, ref) {
deleteFN();
},
window.qBittorrent.TransferList = (function() {
const exports = function() {
return {
contextMenu: contextMenu,
};
};
setLocation: function(element, ref) {
setLocationFN();
},
//create a context menu
const contextMenu = new window.qBittorrent.ContextMenu.TorrentsTableContextMenu({
targets: '.torrentsTableContextMenuTarget',
menu: 'torrentsTableMenu',
actions: {
start: function(element, ref) {
startFN();
},
pause: function(element, ref) {
pauseFN();
},
forceStart: function(element, ref) {
setForceStartFN();
},
rename: function(element, ref) {
renameFN();
},
queueTop: function(element, ref) {
setQueuePositionFN('topPrio');
},
queueUp: function(element, ref) {
setQueuePositionFN('increasePrio');
},
queueDown: function(element, ref) {
setQueuePositionFN('decreasePrio');
},
queueBottom: function(element, ref) {
setQueuePositionFN('bottomPrio');
},
delete: function(element, ref) {
deleteFN();
},
downloadLimit: function(element, ref) {
downloadLimitFN();
},
uploadLimit: function(element, ref) {
uploadLimitFN();
},
shareRatio: function(element, ref) {
shareRatioFN();
},
setLocation: function(element, ref) {
setLocationFN();
},
sequentialDownload: function(element, ref) {
toggleSequentialDownloadFN();
},
firstLastPiecePrio: function(element, ref) {
toggleFirstLastPiecePrioFN();
},
rename: function(element, ref) {
renameFN();
},
queueTop: function(element, ref) {
setQueuePositionFN('topPrio');
},
queueUp: function(element, ref) {
setQueuePositionFN('increasePrio');
},
queueDown: function(element, ref) {
setQueuePositionFN('decreasePrio');
},
queueBottom: function(element, ref) {
setQueuePositionFN('bottomPrio');
},
autoTorrentManagement: function(element, ref) {
autoTorrentManagementFN();
},
forceRecheck: function(element, ref) {
recheckFN();
},
forceReannounce: function(element, ref) {
reannounceFN();
},
downloadLimit: function(element, ref) {
downloadLimitFN();
},
uploadLimit: function(element, ref) {
uploadLimitFN();
},
shareRatio: function(element, ref) {
shareRatioFN();
},
superSeeding: function(element, ref) {
setSuperSeedingFN(!ref.getItemChecked('superSeeding'));
sequentialDownload: function(element, ref) {
toggleSequentialDownloadFN();
},
firstLastPiecePrio: function(element, ref) {
toggleFirstLastPiecePrioFN();
},
autoTorrentManagement: function(element, ref) {
autoTorrentManagementFN();
},
forceRecheck: function(element, ref) {
recheckFN();
},
forceReannounce: function(element, ref) {
reannounceFN();
},
superSeeding: function(element, ref) {
setSuperSeedingFN(!ref.getItemChecked('superSeeding'));
}
},
offsets: {
x: -15,
y: 2
}
},
offsets: {
x: -15,
y: 2
}
});
});
torrentsTable.setup('torrentsTableDiv', 'torrentsTableFixedHeaderDiv', torrentsTableContextMenu);
torrentsTable.setup('torrentsTableDiv', 'torrentsTableFixedHeaderDiv', contextMenu);
return exports();
})();
</script>