diff --git a/src/webui/www/private/addpeers.html b/src/webui/www/private/addpeers.html
index e90ac099c..93b774e5f 100644
--- a/src/webui/www/private/addpeers.html
+++ b/src/webui/www/private/addpeers.html
@@ -61,7 +61,7 @@
QBT_TR(List of peers to add (one IP per line):)QBT_TR[CONTEXT=PeersAdditionDialog]
-
+
diff --git a/src/webui/www/private/download.html b/src/webui/www/private/download.html
index 918a264db..5dfe84cc8 100644
--- a/src/webui/www/private/download.html
+++ b/src/webui/www/private/download.html
@@ -27,7 +27,7 @@
- |
-
+
diff --git a/src/webui/www/private/newcategory.html b/src/webui/www/private/newcategory.html
index b2cf42d88..8e2135ab2 100644
--- a/src/webui/www/private/newcategory.html
+++ b/src/webui/www/private/newcategory.html
@@ -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;
diff --git a/src/webui/www/private/newtag.html b/src/webui/www/private/newtag.html
index d1b7d4a3a..30ab09529 100644
--- a/src/webui/www/private/newtag.html
+++ b/src/webui/www/private/newtag.html
@@ -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]';
diff --git a/src/webui/www/private/scripts/client.js b/src/webui/www/private/scripts/client.js
index 87fca4150..826228738 100644
--- a/src/webui/www/private/scripts/client.js
+++ b/src/webui/www/private/scripts/client.js
@@ -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 = ''
+ ''
- + escapeHtml(text) + ' (' + count + ')' + '';
+ + window.qBittorrent.Misc.escapeHtml(text) + ' (' + count + ')' + '';
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 = ''
+ ''
- + escapeHtml(text) + ' (' + count + ')' + '';
+ + window.qBittorrent.Misc.escapeHtml(text) + ' (' + count + ')' + '';
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) {
diff --git a/src/webui/www/private/scripts/contextmenu.js b/src/webui/www/private/scripts/contextmenu.js
index 310f520f8..0d16525f9 100644
--- a/src/webui/www/private/scripts/contextmenu.js
+++ b/src/webui/www/private/scripts/contextmenu.js
@@ -28,497 +28,515 @@
'use strict';
-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
+if (window.qBittorrent === undefined) {
+ window.qBittorrent = {};
+}
+
+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);
-
- //option diffs menu
- this.menu = $(this.options.menu);
- this.targets = $$(this.options.targets);
-
- //fx
- this.fx = new Fx.Tween(this.menu, {
- property: 'opacity',
- duration: this.options.fadeSpeed,
- onComplete: function() {
- if (this.getStyle('opacity')) {
- this.setStyle('visibility', 'visible');
- }
- else {
- this.setStyle('visibility', 'hidden');
- }
- }.bind(this.menu)
- });
- //hide and begin the listener
- this.hide().startListener();
+ //initialization
+ initialize: function(options) {
+ //set options
+ this.setOptions(options);
+
+ //option diffs menu
+ this.menu = $(this.options.menu);
+ this.targets = $$(this.options.targets);
+
+ //fx
+ this.fx = new Fx.Tween(this.menu, {
+ property: 'opacity',
+ duration: this.options.fadeSpeed,
+ onComplete: function() {
+ if (this.getStyle('opacity')) {
+ this.setStyle('visibility', 'visible');
+ }
+ else {
+ this.setStyle('visibility', 'hidden');
+ }
+ }.bind(this.menu)
+ });
- //hide 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
+ //hide and begin the listener
+ this.hide().startListener();
+
+ //hide the menu
+ this.menu.setStyles({
+ 'position': 'absolute',
+ 'top': '-900000px',
+ 'display': 'block'
});
- }
- },
-
- 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) {
+ },
+
+ 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();
- if (!item.hasClass('disabled')) {
- this.execute(item.get('href').split('#')[1], $(this.options.element));
- this.fireEvent('click', [item, e]);
- }
+ clearTimeout(this.touchstartTimer);
+ this.hide();
+
+ const touchstartEvent = e;
+ this.touchstartTimer = setTimeout(function() {
+ this.triggerMenu(touchstartEvent, elem);
+ }.bind(this), this.options.touchTimer);
}.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;
+ elem.addEvent('touchend', function(e) {
+ e.preventDefault();
+ clearTimeout(this.touchstartTimer);
+ }.bind(this));
+ },
- if (data['f_l_piece_prio'] !== true)
- all_are_f_l_piece_prio = false;
- else
- there_are_f_l_piece_prio = true;
+ addTarget: function(t) {
+ this.targets[this.targets.length] = t;
+ this.setupEventListeners(t);
+ },
- if (data['progress'] != 1.0) // not downloaded
- all_are_downloaded = false;
- else if (data['super_seeding'] !== true)
- all_are_super_seeding = false;
+ triggerMenu: function(e, el) {
+ if (this.options.disabled)
+ return;
- if (data['state'] != 'pausedUP' && data['state'] != 'pausedDL')
- all_are_paused = false;
- else
- there_are_paused = true;
+ //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();
+ },
- if (data['force_start'] !== true)
- all_are_force_start = false;
- else
- there_are_force_start = true;
+ //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));
+ },
- 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;
- else
- tag.checked = tag.checked && tagExists;
+ 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;
+ },
- let show_seq_dl = true;
+ setItemChecked: function(item, checked) {
+ this.menu.getElement('a[href$=' + item + ']').firstChild.style.opacity =
+ checked ? '1' : '0';
+ return this;
+ },
- if (!all_are_seq_dl && there_are_seq_dl)
- show_seq_dl = false;
+ getItemChecked: function(item) {
+ return '0' != this.menu.getElement('a[href$=' + item + ']').firstChild.style.opacity;
+ },
- let show_f_l_piece_prio = true;
+ //hide an item
+ hideItem: function(item) {
+ this.menu.getElement('a[href$=' + item + ']').parentNode.addClass('invisible');
+ return this;
+ },
- if (!all_are_f_l_piece_prio && there_are_f_l_piece_prio)
- show_f_l_piece_prio = false;
+ //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;
+ },
- 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);
+ //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;
}
- 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');
+ });
+
+ 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 (show_seq_dl)
- this.showItem('sequentialDownload');
- else
- this.hideItem('sequentialDownload');
+ if (data['f_l_piece_prio'] !== true)
+ all_are_f_l_piece_prio = false;
+ else
+ there_are_f_l_piece_prio = true;
- if (show_f_l_piece_prio)
- this.showItem('firstLastPiecePrio');
- else
+ 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;
+ 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');
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');
- this.setItemChecked('sequentialDownload', all_are_seq_dl);
- this.setItemChecked('firstLastPiecePrio', all_are_f_l_piece_prio);
+ if (show_seq_dl)
+ this.showItem('sequentialDownload');
+ else
+ this.hideItem('sequentialDownload');
- this.showItem('downloadLimit');
- this.menu.getElement('a[href$=uploadLimit]').parentNode.removeClass('separator');
- this.hideItem('superSeeding');
- }
+ if (show_f_l_piece_prio)
+ this.showItem('firstLastPiecePrio');
+ else
+ this.hideItem('firstLastPiecePrio');
- 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);
- }
+ this.setItemChecked('sequentialDownload', all_are_seq_dl);
+ this.setItemChecked('firstLastPiecePrio', all_are_f_l_piece_prio);
- 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: ' QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]'
- }));
- categoryList.appendChild(new Element('li', {
- html: ' QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]'
- }));
-
- 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: ' ' + escapeHtml(categoryName) + ''
- });
- if (first) {
- el.addClass('separator');
- first = false;
+ this.showItem('downloadLimit');
+ this.menu.getElement('a[href$=uploadLimit]').parentNode.removeClass('separator');
+ this.hideItem('superSeeding');
}
- categoryList.appendChild(el);
- });
- },
-
- updateTagsSubMenu: function(tagList) {
- const contextTagList = $('contextTagList');
- while (contextTagList.firstChild !== null)
- contextTagList.removeChild(contextTagList.firstChild);
-
- contextTagList.appendChild(new Element('li', {
- html: ''
- + ''
- + ' QBT_TR(Add...)QBT_TR[CONTEXT=TransferListWidget]'
- + ''
- }));
- contextTagList.appendChild(new Element('li', {
- html: ''
- + ''
- + ' QBT_TR(Remove All)QBT_TR[CONTEXT=TransferListWidget]'
- + ''
- }));
-
- 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: ''
- + ' ' + escapeHtml(tagName)
- + ''
+
+ 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: ' QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]'
+ }));
+ categoryList.appendChild(new Element('li', {
+ html: ' QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]'
+ }));
+
+ 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: ' ' + window.qBittorrent.Misc.escapeHtml(categoryName) + ''
+ });
+ 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: ''
+ + ''
+ + ' QBT_TR(Add...)QBT_TR[CONTEXT=TransferListWidget]'
+ + ''
+ }));
+ contextTagList.appendChild(new Element('li', {
+ html: ''
+ + ''
+ + ' QBT_TR(Remove All)QBT_TR[CONTEXT=TransferListWidget]'
+ + ''
+ }));
+
+ 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: ''
+ + ' ' + window.qBittorrent.Misc.escapeHtml(tagName)
+ + ''
+ });
+ 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,
-
- 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;
- };
+ });
+
+ const SearchPluginsTableContextMenu = new Class({
+ Extends: ContextMenu,
- this.showItem('Enabled');
- this.setItemChecked('Enabled', this.options.element.getChildren("td")[enabledColumnIndex()].get("html") === "Yes");
+ 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('Uninstall');
+ }
+ });
- this.showItem('Uninstall');
- }
-});
+ return exports();
+})();
diff --git a/src/webui/www/private/scripts/download.js b/src/webui/www/private/scripts/download.js
index 067105c4e..1fa8a7e0d 100644
--- a/src/webui/www/private/scripts/download.js
+++ b/src/webui/www/private/scripts/download.js
@@ -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;
- }
- else {
- $('autoTMM').selectedIndex = 0;
+ if (pref.auto_tmm_enabled == 1) {
+ $('autoTMM').selectedIndex = 1;
+ $('savepath').disabled = true;
+ }
+ 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;
}
- }).send();
-};
+ else {
+ item.nextElementSibling.hidden = true;
+ const text = item.options[item.selectedIndex].innerHTML;
+ item.nextElementSibling.value = text;
-const changeCategorySelect = function(item) {
- if (item.value == "\\other") {
- item.nextElementSibling.hidden = false;
- item.nextElementSibling.value = "";
- item.nextElementSibling.select();
+ 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;
+ }
+ }
+ };
- if ($('autoTMM').selectedIndex == 1)
- $('savepath').value = defaultSavePath;
- }
- else {
- item.nextElementSibling.hidden = true;
- const text = item.options[item.selectedIndex].innerHTML;
- item.nextElementSibling.value = text;
+ const changeTMM = function(item) {
+ if (item.selectedIndex == 1) {
+ $('savepath').disabled = true;
- 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'];
}
- }
-};
-
-const changeTMM = function(item) {
- if (item.selectedIndex == 1) {
- $('savepath').disabled = true;
+ else {
+ $('savepath').disabled = false;
+ $('savepath').value = defaultSavePath;
+ }
+ };
- 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();
+ });
-$(window).addEventListener("load", function() {
- getPreferences();
- getCategories();
-});
+ return exports();
+})();
diff --git a/src/webui/www/private/scripts/dynamicTable.js b/src/webui/www/private/scripts/dynamicTable.js
index 81d308a8c..d66f77de1 100644
--- a/src/webui/www/private/scripts/dynamicTable.js
+++ b/src/webui/www/private/scripts/dynamicTable.js
@@ -33,1956 +33,1975 @@
'use strict';
-let DynamicTableHeaderContextMenuClass = null;
-let ProgressColumnWidth = -1;
-
-const DynamicTable = new Class({
-
- initialize: function() {},
-
- setup: function(dynamicTableDivId, dynamicTableFixedHeaderDivId, contextMenu) {
- this.dynamicTableDivId = dynamicTableDivId;
- this.dynamicTableFixedHeaderDivId = dynamicTableFixedHeaderDivId;
- this.fixedTableHeader = $(dynamicTableFixedHeaderDivId).getElements('tr')[0];
- this.hiddenTableHeader = $(dynamicTableDivId).getElements('tr')[0];
- this.tableBody = $(dynamicTableDivId).getElements('tbody')[0];
- this.rows = new Hash();
- this.selectedRows = [];
- this.columns = [];
- this.contextMenu = contextMenu;
- this.sortedColumn = LocalPreferences.get('sorted_column_' + this.dynamicTableDivId, 0);
- this.reverseSort = LocalPreferences.get('reverse_sort_' + this.dynamicTableDivId, '0');
- this.initColumns();
- this.loadColumnsOrder();
- this.updateTableHeaders();
- this.setupCommonEvents();
- this.setupHeaderEvents();
- this.setupHeaderMenu();
- this.setSortedColumnIcon(this.sortedColumn, null, (this.reverseSort === '1'));
- },
-
- setupCommonEvents: function() {
- const scrollFn = function() {
- $(this.dynamicTableFixedHeaderDivId).getElements('table')[0].style.left = -$(this.dynamicTableDivId).scrollLeft + 'px';
- }.bind(this);
-
- $(this.dynamicTableDivId).addEvent('scroll', scrollFn);
-
- // if the table exists within a panel
- if ($(this.dynamicTableDivId).getParent('.panel')) {
- const resizeFn = function() {
- const panel = $(this.dynamicTableDivId).getParent('.panel');
- let h = panel.getBoundingClientRect().height - $(this.dynamicTableFixedHeaderDivId).getBoundingClientRect().height;
- $(this.dynamicTableDivId).style.height = h + 'px';
-
- // Workaround due to inaccurate calculation of elements heights by browser
-
- let n = 2;
-
- while (panel.clientWidth != panel.offsetWidth && n > 0) { // is panel vertical scrollbar visible ?
- --n;
- h -= 0.5;
- $(this.dynamicTableDivId).style.height = h + 'px';
- }
-
- this.lastPanelHeight = panel.getBoundingClientRect().height;
+if (window.qBittorrent === undefined) {
+ window.qBittorrent = {};
+}
+
+window.qBittorrent.DynamicTable = (function() {
+ const exports = function() {
+ return {
+ TorrentsTable: TorrentsTable,
+ TorrentPeersTable: TorrentPeersTable,
+ SearchResultsTable: SearchResultsTable,
+ SearchPluginsTable: SearchPluginsTable,
+ TorrentTrackersTable: TorrentTrackersTable,
+ TorrentFilesTable: TorrentFilesTable
+ };
+ };
+
+ let DynamicTableHeaderContextMenuClass = null;
+ let ProgressColumnWidth = -1;
+
+ const DynamicTable = new Class({
+
+ initialize: function() {},
+
+ setup: function(dynamicTableDivId, dynamicTableFixedHeaderDivId, contextMenu) {
+ this.dynamicTableDivId = dynamicTableDivId;
+ this.dynamicTableFixedHeaderDivId = dynamicTableFixedHeaderDivId;
+ this.fixedTableHeader = $(dynamicTableFixedHeaderDivId).getElements('tr')[0];
+ this.hiddenTableHeader = $(dynamicTableDivId).getElements('tr')[0];
+ this.tableBody = $(dynamicTableDivId).getElements('tbody')[0];
+ this.rows = new Hash();
+ this.selectedRows = [];
+ this.columns = [];
+ this.contextMenu = contextMenu;
+ this.sortedColumn = LocalPreferences.get('sorted_column_' + this.dynamicTableDivId, 0);
+ this.reverseSort = LocalPreferences.get('reverse_sort_' + this.dynamicTableDivId, '0');
+ this.initColumns();
+ this.loadColumnsOrder();
+ this.updateTableHeaders();
+ this.setupCommonEvents();
+ this.setupHeaderEvents();
+ this.setupHeaderMenu();
+ this.setSortedColumnIcon(this.sortedColumn, null, (this.reverseSort === '1'));
+ },
+
+ setupCommonEvents: function() {
+ const scrollFn = function() {
+ $(this.dynamicTableFixedHeaderDivId).getElements('table')[0].style.left = -$(this.dynamicTableDivId).scrollLeft + 'px';
}.bind(this);
- $(this.dynamicTableDivId).getParent('.panel').addEvent('resize', resizeFn);
+ $(this.dynamicTableDivId).addEvent('scroll', scrollFn);
+
+ // if the table exists within a panel
+ if ($(this.dynamicTableDivId).getParent('.panel')) {
+ const resizeFn = function() {
+ const panel = $(this.dynamicTableDivId).getParent('.panel');
+ let h = panel.getBoundingClientRect().height - $(this.dynamicTableFixedHeaderDivId).getBoundingClientRect().height;
+ $(this.dynamicTableDivId).style.height = h + 'px';
+
+ // Workaround due to inaccurate calculation of elements heights by browser
- this.lastPanelHeight = 0;
+ let n = 2;
- // Workaround. Resize event is called not always (for example it isn't called when browser window changes it's size)
+ while (panel.clientWidth != panel.offsetWidth && n > 0) { // is panel vertical scrollbar visible ?
+ --n;
+ h -= 0.5;
+ $(this.dynamicTableDivId).style.height = h + 'px';
+ }
- const checkResizeFn = function() {
- const panel = $(this.dynamicTableDivId).getParent('.panel');
- if (this.lastPanelHeight != panel.getBoundingClientRect().height) {
this.lastPanelHeight = panel.getBoundingClientRect().height;
- panel.fireEvent('resize');
- }
- }.bind(this);
+ }.bind(this);
- setInterval(checkResizeFn, 500);
- }
- },
+ $(this.dynamicTableDivId).getParent('.panel').addEvent('resize', resizeFn);
- setupHeaderEvents: function() {
- this.currentHeaderAction = '';
- this.canResize = false;
+ this.lastPanelHeight = 0;
- const resetElementBorderStyle = function(el, side) {
- if (side === 'left' || side !== 'right') {
- el.setStyle('border-left-style', '');
- el.setStyle('border-left-color', '');
- el.setStyle('border-left-width', '');
- }
- if (side === 'right' || side !== 'left') {
- el.setStyle('border-right-style', '');
- el.setStyle('border-right-color', '');
- el.setStyle('border-right-width', '');
+ // Workaround. Resize event is called not always (for example it isn't called when browser window changes it's size)
+
+ const checkResizeFn = function() {
+ const panel = $(this.dynamicTableDivId).getParent('.panel');
+ if (this.lastPanelHeight != panel.getBoundingClientRect().height) {
+ this.lastPanelHeight = panel.getBoundingClientRect().height;
+ panel.fireEvent('resize');
+ }
+ }.bind(this);
+
+ setInterval(checkResizeFn, 500);
}
- };
+ },
- const mouseMoveFn = function(e) {
- const brect = e.target.getBoundingClientRect();
- const mouseXRelative = e.event.clientX - brect.left;
- if (this.currentHeaderAction === '') {
- if (brect.width - mouseXRelative < 5) {
- this.resizeTh = e.target;
- this.canResize = true;
- e.target.getParent("tr").style.cursor = 'col-resize';
- }
- else if ((mouseXRelative < 5) && e.target.getPrevious('[class=""]')) {
- this.resizeTh = e.target.getPrevious('[class=""]');
- this.canResize = true;
- e.target.getParent("tr").style.cursor = 'col-resize';
- }
- else {
- this.canResize = false;
- e.target.getParent("tr").style.cursor = '';
+ setupHeaderEvents: function() {
+ this.currentHeaderAction = '';
+ this.canResize = false;
+
+ const resetElementBorderStyle = function(el, side) {
+ if (side === 'left' || side !== 'right') {
+ el.setStyle('border-left-style', '');
+ el.setStyle('border-left-color', '');
+ el.setStyle('border-left-width', '');
}
- }
- if (this.currentHeaderAction === 'drag') {
- const previousVisibleSibling = e.target.getPrevious('[class=""]');
- let borderChangeElement = previousVisibleSibling;
- let changeBorderSide = 'right';
-
- if (mouseXRelative > brect.width / 2) {
- borderChangeElement = e.target;
- this.dropSide = 'right';
+ if (side === 'right' || side !== 'left') {
+ el.setStyle('border-right-style', '');
+ el.setStyle('border-right-color', '');
+ el.setStyle('border-right-width', '');
}
- else {
- this.dropSide = 'left';
+ };
+
+ const mouseMoveFn = function(e) {
+ const brect = e.target.getBoundingClientRect();
+ const mouseXRelative = e.event.clientX - brect.left;
+ if (this.currentHeaderAction === '') {
+ if (brect.width - mouseXRelative < 5) {
+ this.resizeTh = e.target;
+ this.canResize = true;
+ e.target.getParent("tr").style.cursor = 'col-resize';
+ }
+ else if ((mouseXRelative < 5) && e.target.getPrevious('[class=""]')) {
+ this.resizeTh = e.target.getPrevious('[class=""]');
+ this.canResize = true;
+ e.target.getParent("tr").style.cursor = 'col-resize';
+ }
+ else {
+ this.canResize = false;
+ e.target.getParent("tr").style.cursor = '';
+ }
}
+ if (this.currentHeaderAction === 'drag') {
+ const previousVisibleSibling = e.target.getPrevious('[class=""]');
+ let borderChangeElement = previousVisibleSibling;
+ let changeBorderSide = 'right';
+
+ if (mouseXRelative > brect.width / 2) {
+ borderChangeElement = e.target;
+ this.dropSide = 'right';
+ }
+ else {
+ this.dropSide = 'left';
+ }
- e.target.getParent("tr").style.cursor = 'move';
+ e.target.getParent("tr").style.cursor = 'move';
- if (!previousVisibleSibling) { // right most column
- borderChangeElement = e.target;
+ if (!previousVisibleSibling) { // right most column
+ borderChangeElement = e.target;
+
+ if (mouseXRelative <= brect.width / 2)
+ changeBorderSide = 'left';
+ }
- if (mouseXRelative <= brect.width / 2)
- changeBorderSide = 'left';
+ borderChangeElement.setStyle('border-' + changeBorderSide + '-style', 'solid');
+ borderChangeElement.setStyle('border-' + changeBorderSide + '-color', '#e60');
+ borderChangeElement.setStyle('border-' + changeBorderSide + '-width', 'initial');
+
+ resetElementBorderStyle(borderChangeElement, changeBorderSide === 'right' ? 'left' : 'right');
+
+ borderChangeElement.getSiblings('[class=""]').each(function(el) {
+ resetElementBorderStyle(el);
+ });
}
+ this.lastHoverTh = e.target;
+ this.lastClientX = e.event.clientX;
+ }.bind(this);
- borderChangeElement.setStyle('border-' + changeBorderSide + '-style', 'solid');
- borderChangeElement.setStyle('border-' + changeBorderSide + '-color', '#e60');
- borderChangeElement.setStyle('border-' + changeBorderSide + '-width', 'initial');
+ const mouseOutFn = function(e) {
+ resetElementBorderStyle(e.target);
+ }.bind(this);
+
+ const onBeforeStart = function(el) {
+ this.clickedTh = el;
+ this.currentHeaderAction = 'start';
+ this.dragMovement = false;
+ this.dragStartX = this.lastClientX;
+ }.bind(this);
+
+ const onStart = function(el, event) {
+ if (this.canResize) {
+ this.currentHeaderAction = 'resize';
+ this.startWidth = this.resizeTh.getStyle('width').toFloat();
+ }
+ else {
+ this.currentHeaderAction = 'drag';
+ el.setStyle('background-color', '#C1D5E7');
+ }
+ }.bind(this);
- resetElementBorderStyle(borderChangeElement, changeBorderSide === 'right' ? 'left' : 'right');
+ const onDrag = function(el, event) {
+ if (this.currentHeaderAction === 'resize') {
+ let width = this.startWidth + (event.page.x - this.dragStartX);
+ if (width < 16)
+ width = 16;
+ this.columns[this.resizeTh.columnName].width = width;
+ this.updateColumn(this.resizeTh.columnName);
+ }
+ }.bind(this);
- borderChangeElement.getSiblings('[class=""]').each(function(el) {
+ const onComplete = function(el, event) {
+ resetElementBorderStyle(this.lastHoverTh);
+ el.setStyle('background-color', '');
+ if (this.currentHeaderAction === 'resize')
+ LocalPreferences.set('column_' + this.resizeTh.columnName + '_width_' + this.dynamicTableDivId, this.columns[this.resizeTh.columnName].width);
+ if ((this.currentHeaderAction === 'drag') && (el !== this.lastHoverTh)) {
+ this.saveColumnsOrder();
+ const val = LocalPreferences.get('columns_order_' + this.dynamicTableDivId).split(',');
+ val.erase(el.columnName);
+ let pos = val.indexOf(this.lastHoverTh.columnName);
+ if (this.dropSide === 'right') ++pos;
+ val.splice(pos, 0, el.columnName);
+ LocalPreferences.set('columns_order_' + this.dynamicTableDivId, val.join(','));
+ this.loadColumnsOrder();
+ this.updateTableHeaders();
+ while (this.tableBody.firstChild)
+ this.tableBody.removeChild(this.tableBody.firstChild);
+ this.updateTable(true);
+ }
+ if (this.currentHeaderAction === 'drag') {
resetElementBorderStyle(el);
+ el.getSiblings('[class=""]').each(function(el) {
+ resetElementBorderStyle(el);
+ });
+ }
+ this.currentHeaderAction = '';
+ }.bind(this);
+
+ const onCancel = function(el) {
+ this.currentHeaderAction = '';
+ this.setSortedColumn(el.columnName);
+ }.bind(this);
+
+ const ths = this.fixedTableHeader.getElements('th');
+
+ for (let i = 0; i < ths.length; ++i) {
+ const th = ths[i];
+ th.addEvent('mousemove', mouseMoveFn);
+ th.addEvent('mouseout', mouseOutFn);
+ th.makeResizable({
+ modifiers: {
+ x: '',
+ y: ''
+ },
+ onBeforeStart: onBeforeStart,
+ onStart: onStart,
+ onDrag: onDrag,
+ onComplete: onComplete,
+ onCancel: onCancel
});
}
- this.lastHoverTh = e.target;
- this.lastClientX = e.event.clientX;
- }.bind(this);
-
- const mouseOutFn = function(e) {
- resetElementBorderStyle(e.target);
- }.bind(this);
-
- const onBeforeStart = function(el) {
- this.clickedTh = el;
- this.currentHeaderAction = 'start';
- this.dragMovement = false;
- this.dragStartX = this.lastClientX;
- }.bind(this);
-
- const onStart = function(el, event) {
- if (this.canResize) {
- this.currentHeaderAction = 'resize';
- this.startWidth = this.resizeTh.getStyle('width').toFloat();
- }
- else {
- this.currentHeaderAction = 'drag';
- el.setStyle('background-color', '#C1D5E7');
- }
- }.bind(this);
-
- const onDrag = function(el, event) {
- if (this.currentHeaderAction === 'resize') {
- let width = this.startWidth + (event.page.x - this.dragStartX);
- if (width < 16)
- width = 16;
- this.columns[this.resizeTh.columnName].width = width;
- this.updateColumn(this.resizeTh.columnName);
- }
- }.bind(this);
-
- const onComplete = function(el, event) {
- resetElementBorderStyle(this.lastHoverTh);
- el.setStyle('background-color', '');
- if (this.currentHeaderAction === 'resize')
- LocalPreferences.set('column_' + this.resizeTh.columnName + '_width_' + this.dynamicTableDivId, this.columns[this.resizeTh.columnName].width);
- if ((this.currentHeaderAction === 'drag') && (el !== this.lastHoverTh)) {
- this.saveColumnsOrder();
- const val = LocalPreferences.get('columns_order_' + this.dynamicTableDivId).split(',');
- val.erase(el.columnName);
- let pos = val.indexOf(this.lastHoverTh.columnName);
- if (this.dropSide === 'right') ++pos;
- val.splice(pos, 0, el.columnName);
- LocalPreferences.set('columns_order_' + this.dynamicTableDivId, val.join(','));
- this.loadColumnsOrder();
- this.updateTableHeaders();
- while (this.tableBody.firstChild)
- this.tableBody.removeChild(this.tableBody.firstChild);
- this.updateTable(true);
- }
- if (this.currentHeaderAction === 'drag') {
- resetElementBorderStyle(el);
- el.getSiblings('[class=""]').each(function(el) {
- resetElementBorderStyle(el);
+ },
+
+ setupDynamicTableHeaderContextMenuClass: function() {
+ if (!DynamicTableHeaderContextMenuClass) {
+ DynamicTableHeaderContextMenuClass = new Class({
+ Extends: window.qBittorrent.ContextMenu.ContextMenu,
+ updateMenuItems: function() {
+ for (let i = 0; i < this.dynamicTable.columns.length; ++i) {
+ if (this.dynamicTable.columns[i].caption === '')
+ continue;
+ if (this.dynamicTable.columns[i].visible !== '0')
+ this.setItemChecked(this.dynamicTable.columns[i].name, true);
+ else
+ this.setItemChecked(this.dynamicTable.columns[i].name, false);
+ }
+ }
});
}
- this.currentHeaderAction = '';
- }.bind(this);
+ },
- const onCancel = function(el) {
- this.currentHeaderAction = '';
- this.setSortedColumn(el.columnName);
- }.bind(this);
-
- const ths = this.fixedTableHeader.getElements('th');
-
- for (let i = 0; i < ths.length; ++i) {
- const th = ths[i];
- th.addEvent('mousemove', mouseMoveFn);
- th.addEvent('mouseout', mouseOutFn);
- th.makeResizable({
- modifiers: {
- x: '',
- y: ''
- },
- onBeforeStart: onBeforeStart,
- onStart: onStart,
- onDrag: onDrag,
- onComplete: onComplete,
- onCancel: onCancel
- });
- }
- },
-
- setupDynamicTableHeaderContextMenuClass: function() {
- if (!DynamicTableHeaderContextMenuClass) {
- DynamicTableHeaderContextMenuClass = new Class({
- Extends: ContextMenu,
- updateMenuItems: function() {
- for (let i = 0; i < this.dynamicTable.columns.length; ++i) {
- if (this.dynamicTable.columns[i].caption === '')
- continue;
- if (this.dynamicTable.columns[i].visible !== '0')
- this.setItemChecked(this.dynamicTable.columns[i].name, true);
- else
- this.setItemChecked(this.dynamicTable.columns[i].name, false);
- }
- }
+ showColumn: function(columnName, show) {
+ this.columns[columnName].visible = show ? '1' : '0';
+ LocalPreferences.set('column_' + columnName + '_visible_' + this.dynamicTableDivId, show ? '1' : '0');
+ this.updateColumn(columnName);
+ },
+
+ setupHeaderMenu: function() {
+ this.setupDynamicTableHeaderContextMenuClass();
+
+ const menuId = this.dynamicTableDivId + '_headerMenu';
+
+ const ul = new Element('ul', {
+ id: menuId,
+ class: 'contextMenu scrollableMenu'
});
- }
- },
- showColumn: function(columnName, show) {
- this.columns[columnName].visible = show ? '1' : '0';
- LocalPreferences.set('column_' + columnName + '_visible_' + this.dynamicTableDivId, show ? '1' : '0');
- this.updateColumn(columnName);
- },
+ const createLi = function(columnName, text) {
+ const html = '' + window.qBittorrent.Misc.escapeHtml(text) + '';
+ return new Element('li', {
+ html: html
+ });
+ };
- setupHeaderMenu: function() {
- this.setupDynamicTableHeaderContextMenuClass();
+ const actions = {};
- const menuId = this.dynamicTableDivId + '_headerMenu';
+ const onMenuItemClicked = function(element, ref, action) {
+ this.showColumn(action, this.columns[action].visible === '0');
+ }.bind(this);
- const ul = new Element('ul', {
- id: menuId,
- class: 'contextMenu scrollableMenu'
- });
+ for (let i = 0; i < this.columns.length; ++i) {
+ const text = this.columns[i].caption;
+ if (text === '')
+ continue;
+ ul.appendChild(createLi(this.columns[i].name, text));
+ actions[this.columns[i].name] = onMenuItemClicked;
+ }
- const createLi = function(columnName, text) {
- const html = '' + escapeHtml(text) + '';
- return new Element('li', {
- html: html
+ ul.inject(document.body);
+
+ this.headerContextMenu = new DynamicTableHeaderContextMenuClass({
+ targets: '#' + this.dynamicTableFixedHeaderDivId + ' tr',
+ actions: actions,
+ menu: menuId,
+ offsets: {
+ x: -15,
+ y: 2
+ }
});
- };
- const actions = {};
+ this.headerContextMenu.dynamicTable = this;
+ },
+
+ initColumns: function() {},
+
+ newColumn: function(name, style, caption, defaultWidth, defaultVisible) {
+ const column = {};
+ column['name'] = name;
+ column['title'] = name;
+ column['visible'] = LocalPreferences.get('column_' + name + '_visible_' + this.dynamicTableDivId, defaultVisible ? '1' : '0');
+ column['force_hide'] = false;
+ column['caption'] = caption;
+ column['style'] = style;
+ column['width'] = LocalPreferences.get('column_' + name + '_width_' + this.dynamicTableDivId, defaultWidth);
+ column['dataProperties'] = [name];
+ column['getRowValue'] = function(row, pos) {
+ if (pos === undefined)
+ pos = 0;
+ return row['full_data'][this.dataProperties[pos]];
+ };
+ column['compareRows'] = function(row1, row2) {
+ if (this.getRowValue(row1) < this.getRowValue(row2))
+ return -1;
+ else if (this.getRowValue(row1) > this.getRowValue(row2))
+ return 1;
+ else return 0;
+ };
+ column['updateTd'] = function(td, row) {
+ const value = this.getRowValue(row)
+ td.innerHTML = value;
+ td.title = value;
+ };
+ column['onResize'] = null;
+ this.columns.push(column);
+ this.columns[name] = column;
+
+ this.hiddenTableHeader.appendChild(new Element('th'));
+ this.fixedTableHeader.appendChild(new Element('th'));
+ },
+
+ loadColumnsOrder: function() {
+ const columnsOrder = [];
+ const val = LocalPreferences.get('columns_order_' + this.dynamicTableDivId);
+ if (val === null || val === undefined) return;
+ val.split(',').forEach(function(v) {
+ if ((v in this.columns) && (!columnsOrder.contains(v)))
+ columnsOrder.push(v);
+ }.bind(this));
- const onMenuItemClicked = function(element, ref, action) {
- this.showColumn(action, this.columns[action].visible === '0');
- }.bind(this);
+ for (let i = 0; i < this.columns.length; ++i)
+ if (!columnsOrder.contains(this.columns[i].name))
+ columnsOrder.push(this.columns[i].name);
- for (let i = 0; i < this.columns.length; ++i) {
- const text = this.columns[i].caption;
- if (text === '')
- continue;
- ul.appendChild(createLi(this.columns[i].name, text));
- actions[this.columns[i].name] = onMenuItemClicked;
- }
+ for (let i = 0; i < this.columns.length; ++i)
+ this.columns[i] = this.columns[columnsOrder[i]];
+ },
- ul.inject(document.body);
-
- this.headerContextMenu = new DynamicTableHeaderContextMenuClass({
- targets: '#' + this.dynamicTableFixedHeaderDivId + ' tr',
- actions: actions,
- menu: menuId,
- offsets: {
- x: -15,
- y: 2
+ saveColumnsOrder: function() {
+ let val = '';
+ for (let i = 0; i < this.columns.length; ++i) {
+ if (i > 0)
+ val += ',';
+ val += this.columns[i].name;
}
- });
-
- this.headerContextMenu.dynamicTable = this;
- },
-
- initColumns: function() {},
-
- newColumn: function(name, style, caption, defaultWidth, defaultVisible) {
- const column = {};
- column['name'] = name;
- column['title'] = name;
- column['visible'] = LocalPreferences.get('column_' + name + '_visible_' + this.dynamicTableDivId, defaultVisible ? '1' : '0');
- column['force_hide'] = false;
- column['caption'] = caption;
- column['style'] = style;
- column['width'] = LocalPreferences.get('column_' + name + '_width_' + this.dynamicTableDivId, defaultWidth);
- column['dataProperties'] = [name];
- column['getRowValue'] = function(row, pos) {
- if (pos === undefined)
- pos = 0;
- return row['full_data'][this.dataProperties[pos]];
- };
- column['compareRows'] = function(row1, row2) {
- if (this.getRowValue(row1) < this.getRowValue(row2))
- return -1;
- else if (this.getRowValue(row1) > this.getRowValue(row2))
- return 1;
- else return 0;
- };
- column['updateTd'] = function(td, row) {
- const value = this.getRowValue(row)
- td.innerHTML = value;
- td.title = value;
- };
- column['onResize'] = null;
- this.columns.push(column);
- this.columns[name] = column;
-
- this.hiddenTableHeader.appendChild(new Element('th'));
- this.fixedTableHeader.appendChild(new Element('th'));
- },
-
- loadColumnsOrder: function() {
- const columnsOrder = [];
- const val = LocalPreferences.get('columns_order_' + this.dynamicTableDivId);
- if (val === null || val === undefined) return;
- val.split(',').forEach(function(v) {
- if ((v in this.columns) && (!columnsOrder.contains(v)))
- columnsOrder.push(v);
- }.bind(this));
-
- for (let i = 0; i < this.columns.length; ++i)
- if (!columnsOrder.contains(this.columns[i].name))
- columnsOrder.push(this.columns[i].name);
-
- for (let i = 0; i < this.columns.length; ++i)
- this.columns[i] = this.columns[columnsOrder[i]];
- },
-
- saveColumnsOrder: function() {
- let val = '';
- for (let i = 0; i < this.columns.length; ++i) {
- if (i > 0)
- val += ',';
- val += this.columns[i].name;
- }
- LocalPreferences.set('columns_order_' + this.dynamicTableDivId, val);
- },
-
- updateTableHeaders: function() {
- this.updateHeader(this.hiddenTableHeader);
- this.updateHeader(this.fixedTableHeader);
- },
-
- updateHeader: function(header) {
- const ths = header.getElements('th');
-
- for (let i = 0; i < ths.length; ++i) {
- const th = ths[i];
- th._this = this;
- th.setAttribute('title', this.columns[i].caption);
- th.innerHTML = this.columns[i].caption;
- th.setAttribute('style', 'width: ' + this.columns[i].width + 'px;' + this.columns[i].style);
- th.columnName = this.columns[i].name;
- th.addClass('column_' + th.columnName);
- if ((this.columns[i].visible == '0') || this.columns[i].force_hide)
- th.addClass('invisible');
- else
- th.removeClass('invisible');
- }
- },
-
- getColumnPos: function(columnName) {
- for (let i = 0; i < this.columns.length; ++i)
- if (this.columns[i].name == columnName)
- return i;
- return -1;
- },
-
- updateColumn: function(columnName) {
- const pos = this.getColumnPos(columnName);
- const visible = ((this.columns[pos].visible != '0') && !this.columns[pos].force_hide);
- const ths = this.hiddenTableHeader.getElements('th');
- const fths = this.fixedTableHeader.getElements('th');
- const trs = this.tableBody.getElements('tr');
- const style = 'width: ' + this.columns[pos].width + 'px;' + this.columns[pos].style;
-
- ths[pos].setAttribute('style', style);
- fths[pos].setAttribute('style', style);
-
- if (visible) {
- ths[pos].removeClass('invisible');
- fths[pos].removeClass('invisible');
- for (let i = 0; i < trs.length; ++i)
- trs[i].getElements('td')[pos].removeClass('invisible');
- }
- else {
- ths[pos].addClass('invisible');
- fths[pos].addClass('invisible');
- for (let j = 0; j < trs.length; ++j)
- trs[j].getElements('td')[pos].addClass('invisible');
- }
- if (this.columns[pos].onResize !== null) {
- this.columns[pos].onResize(columnName);
- }
- },
-
- getSortedColumn: function() {
- return LocalPreferences.get('sorted_column_' + this.dynamicTableDivId);
- },
-
- setSortedColumn: function(column) {
- if (column != this.sortedColumn) {
- const oldColumn = this.sortedColumn;
- this.sortedColumn = column;
- this.reverseSort = '0';
- this.setSortedColumnIcon(column, oldColumn, false);
- }
- else {
- // Toggle sort order
- this.reverseSort = this.reverseSort === '0' ? '1' : '0';
- this.setSortedColumnIcon(column, null, (this.reverseSort === '1'));
- }
- LocalPreferences.set('sorted_column_' + this.dynamicTableDivId, column);
- LocalPreferences.set('reverse_sort_' + this.dynamicTableDivId, this.reverseSort);
- this.updateTable(false);
- },
-
- setSortedColumnIcon: function(newColumn, oldColumn, isReverse) {
- const getCol = function(headerDivId, colName) {
- const colElem = $$("#" + headerDivId + " .column_" + colName);
- if (colElem.length == 1)
- return colElem[0];
- return null;
- };
+ LocalPreferences.set('columns_order_' + this.dynamicTableDivId, val);
+ },
+
+ updateTableHeaders: function() {
+ this.updateHeader(this.hiddenTableHeader);
+ this.updateHeader(this.fixedTableHeader);
+ },
+
+ updateHeader: function(header) {
+ const ths = header.getElements('th');
+
+ for (let i = 0; i < ths.length; ++i) {
+ const th = ths[i];
+ th._this = this;
+ th.setAttribute('title', this.columns[i].caption);
+ th.innerHTML = this.columns[i].caption;
+ th.setAttribute('style', 'width: ' + this.columns[i].width + 'px;' + this.columns[i].style);
+ th.columnName = this.columns[i].name;
+ th.addClass('column_' + th.columnName);
+ if ((this.columns[i].visible == '0') || this.columns[i].force_hide)
+ th.addClass('invisible');
+ else
+ th.removeClass('invisible');
+ }
+ },
- const colElem = getCol(this.dynamicTableFixedHeaderDivId, newColumn);
- if (colElem !== null) {
- colElem.addClass('sorted');
- if (isReverse)
- colElem.addClass('reverse');
- else
- colElem.removeClass('reverse');
- }
- const oldColElem = getCol(this.dynamicTableFixedHeaderDivId, oldColumn);
- if (oldColElem !== null) {
- oldColElem.removeClass('sorted');
- oldColElem.removeClass('reverse');
- }
- },
-
- getSelectedRowId: function() {
- if (this.selectedRows.length > 0)
- return this.selectedRows[0];
- return '';
- },
-
- isRowSelected: function(rowId) {
- return this.selectedRows.contains(rowId);
- },
-
- altRow: function() {
- if (!MUI.ieLegacySupport)
- return;
-
- const trs = this.tableBody.getElements('tr');
- trs.each(function(el, i) {
- if (i % 2) {
- el.addClass('alt');
+ getColumnPos: function(columnName) {
+ for (let i = 0; i < this.columns.length; ++i)
+ if (this.columns[i].name == columnName)
+ return i;
+ return -1;
+ },
+
+ updateColumn: function(columnName) {
+ const pos = this.getColumnPos(columnName);
+ const visible = ((this.columns[pos].visible != '0') && !this.columns[pos].force_hide);
+ const ths = this.hiddenTableHeader.getElements('th');
+ const fths = this.fixedTableHeader.getElements('th');
+ const trs = this.tableBody.getElements('tr');
+ const style = 'width: ' + this.columns[pos].width + 'px;' + this.columns[pos].style;
+
+ ths[pos].setAttribute('style', style);
+ fths[pos].setAttribute('style', style);
+
+ if (visible) {
+ ths[pos].removeClass('invisible');
+ fths[pos].removeClass('invisible');
+ for (let i = 0; i < trs.length; ++i)
+ trs[i].getElements('td')[pos].removeClass('invisible');
}
else {
- el.removeClass('alt');
+ ths[pos].addClass('invisible');
+ fths[pos].addClass('invisible');
+ for (let j = 0; j < trs.length; ++j)
+ trs[j].getElements('td')[pos].addClass('invisible');
}
- }.bind(this));
- },
-
- selectAll: function() {
- this.deselectAll();
-
- const trs = this.tableBody.getElements('tr');
- for (let i = 0; i < trs.length; ++i) {
- const tr = trs[i];
- this.selectedRows.push(tr.rowId);
- if (!tr.hasClass('selected'))
- tr.addClass('selected');
- }
- },
-
- deselectAll: function() {
- this.selectedRows.empty();
- },
-
- selectRow: function(rowId) {
- this.selectedRows.push(rowId);
- this.setRowClass();
- this.onSelectedRowChanged();
- },
-
- deselectRow: function(rowId) {
- this.selectedRows.erase(rowId);
- this.setRowClass();
- this.onSelectedRowChanged();
- },
-
- selectRows: function(rowId1, rowId2) {
- this.deselectAll();
- if (rowId1 === rowId2) {
- this.selectRow(rowId1);
- return;
- }
+ if (this.columns[pos].onResize !== null) {
+ this.columns[pos].onResize(columnName);
+ }
+ },
+
+ getSortedColumn: function() {
+ return LocalPreferences.get('sorted_column_' + this.dynamicTableDivId);
+ },
+
+ setSortedColumn: function(column) {
+ if (column != this.sortedColumn) {
+ const oldColumn = this.sortedColumn;
+ this.sortedColumn = column;
+ this.reverseSort = '0';
+ this.setSortedColumnIcon(column, oldColumn, false);
+ }
+ else {
+ // Toggle sort order
+ this.reverseSort = this.reverseSort === '0' ? '1' : '0';
+ this.setSortedColumnIcon(column, null, (this.reverseSort === '1'));
+ }
+ LocalPreferences.set('sorted_column_' + this.dynamicTableDivId, column);
+ LocalPreferences.set('reverse_sort_' + this.dynamicTableDivId, this.reverseSort);
+ this.updateTable(false);
+ },
+
+ setSortedColumnIcon: function(newColumn, oldColumn, isReverse) {
+ const getCol = function(headerDivId, colName) {
+ const colElem = $$("#" + headerDivId + " .column_" + colName);
+ if (colElem.length == 1)
+ return colElem[0];
+ return null;
+ };
- let select = false;
- const that = this;
- this.tableBody.getElements('tr').each(function(tr) {
- if ((tr.rowId == rowId1) || (tr.rowId == rowId2)) {
- select = !select;
- that.selectedRows.push(tr.rowId);
+ const colElem = getCol(this.dynamicTableFixedHeaderDivId, newColumn);
+ if (colElem !== null) {
+ colElem.addClass('sorted');
+ if (isReverse)
+ colElem.addClass('reverse');
+ else
+ colElem.removeClass('reverse');
}
- else if (select) {
- that.selectedRows.push(tr.rowId);
+ const oldColElem = getCol(this.dynamicTableFixedHeaderDivId, oldColumn);
+ if (oldColElem !== null) {
+ oldColElem.removeClass('sorted');
+ oldColElem.removeClass('reverse');
}
- });
- this.setRowClass();
- this.onSelectedRowChanged();
- },
-
- reselectRows: function(rowIds) {
- this.deselectAll();
- this.selectedRows = rowIds.slice();
- this.tableBody.getElements('tr').each(function(tr) {
- if (rowIds.indexOf(tr.rowId) > -1)
- tr.addClass('selected');
- });
- },
-
- setRowClass: function() {
- const that = this;
- this.tableBody.getElements('tr').each(function(tr) {
- if (that.isRowSelected(tr.rowId))
- tr.addClass('selected');
- else
- tr.removeClass('selected');
- });
- },
+ },
- onSelectedRowChanged: function() {},
+ getSelectedRowId: function() {
+ if (this.selectedRows.length > 0)
+ return this.selectedRows[0];
+ return '';
+ },
- updateRowData: function(data) {
- const rowId = data['rowId'];
- let row;
+ isRowSelected: function(rowId) {
+ return this.selectedRows.contains(rowId);
+ },
- if (!this.rows.has(rowId)) {
- row = {};
- this.rows.set(rowId, row);
- row['full_data'] = {};
- row['rowId'] = rowId;
- }
- else
- row = this.rows.get(rowId);
+ altRow: function() {
+ if (!MUI.ieLegacySupport)
+ return;
- row['data'] = data;
+ const trs = this.tableBody.getElements('tr');
+ trs.each(function(el, i) {
+ if (i % 2) {
+ el.addClass('alt');
+ }
+ else {
+ el.removeClass('alt');
+ }
+ }.bind(this));
+ },
- for (const x in data)
- row['full_data'][x] = data[x];
- },
+ selectAll: function() {
+ this.deselectAll();
- getFilteredAndSortedRows: function() {
- const filteredRows = [];
+ const trs = this.tableBody.getElements('tr');
+ for (let i = 0; i < trs.length; ++i) {
+ const tr = trs[i];
+ this.selectedRows.push(tr.rowId);
+ if (!tr.hasClass('selected'))
+ tr.addClass('selected');
+ }
+ },
+
+ deselectAll: function() {
+ this.selectedRows.empty();
+ },
+
+ selectRow: function(rowId) {
+ this.selectedRows.push(rowId);
+ this.setRowClass();
+ this.onSelectedRowChanged();
+ },
+
+ deselectRow: function(rowId) {
+ this.selectedRows.erase(rowId);
+ this.setRowClass();
+ this.onSelectedRowChanged();
+ },
+
+ selectRows: function(rowId1, rowId2) {
+ this.deselectAll();
+ if (rowId1 === rowId2) {
+ this.selectRow(rowId1);
+ return;
+ }
- const rows = this.rows.getValues();
+ let select = false;
+ const that = this;
+ this.tableBody.getElements('tr').each(function(tr) {
+ if ((tr.rowId == rowId1) || (tr.rowId == rowId2)) {
+ select = !select;
+ that.selectedRows.push(tr.rowId);
+ }
+ else if (select) {
+ that.selectedRows.push(tr.rowId);
+ }
+ });
+ this.setRowClass();
+ this.onSelectedRowChanged();
+ },
+
+ reselectRows: function(rowIds) {
+ this.deselectAll();
+ this.selectedRows = rowIds.slice();
+ this.tableBody.getElements('tr').each(function(tr) {
+ if (rowIds.indexOf(tr.rowId) > -1)
+ tr.addClass('selected');
+ });
+ },
- for (let i = 0; i < rows.length; ++i) {
- filteredRows.push(rows[i]);
- filteredRows[rows[i].rowId] = rows[i];
- }
+ setRowClass: function() {
+ const that = this;
+ this.tableBody.getElements('tr').each(function(tr) {
+ if (that.isRowSelected(tr.rowId))
+ tr.addClass('selected');
+ else
+ tr.removeClass('selected');
+ });
+ },
- filteredRows.sort(function(row1, row2) {
- const column = this.columns[this.sortedColumn];
- const res = column.compareRows(row1, row2);
- if (this.reverseSort === '0')
- return res;
+ onSelectedRowChanged: function() {},
+
+ updateRowData: function(data) {
+ const rowId = data['rowId'];
+ let row;
+
+ if (!this.rows.has(rowId)) {
+ row = {};
+ this.rows.set(rowId, row);
+ row['full_data'] = {};
+ row['rowId'] = rowId;
+ }
else
- return -res;
- }.bind(this));
- return filteredRows;
- },
-
- getTrByRowId: function(rowId) {
- const trs = this.tableBody.getElements('tr');
- for (let i = 0; i < trs.length; ++i)
- if (trs[i].rowId == rowId)
- return trs[i];
- return null;
- },
-
- updateTable: function(fullUpdate) {
- if (fullUpdate === undefined)
- fullUpdate = false;
-
- const rows = this.getFilteredAndSortedRows();
-
- for (let i = 0; i < this.selectedRows.length; ++i)
- if (!(this.selectedRows[i] in rows)) {
- this.selectedRows.splice(i, 1);
- --i;
+ row = this.rows.get(rowId);
+
+ row['data'] = data;
+
+ for (const x in data)
+ row['full_data'][x] = data[x];
+ },
+
+ getFilteredAndSortedRows: function() {
+ const filteredRows = [];
+
+ const rows = this.rows.getValues();
+
+ for (let i = 0; i < rows.length; ++i) {
+ filteredRows.push(rows[i]);
+ filteredRows[rows[i].rowId] = rows[i];
}
- const trs = this.tableBody.getElements('tr');
+ filteredRows.sort(function(row1, row2) {
+ const column = this.columns[this.sortedColumn];
+ const res = column.compareRows(row1, row2);
+ if (this.reverseSort === '0')
+ return res;
+ else
+ return -res;
+ }.bind(this));
+ return filteredRows;
+ },
- for (let rowPos = 0; rowPos < rows.length; ++rowPos) {
- const rowId = rows[rowPos]['rowId'];
- let tr_found = false;
- for (let j = rowPos; j < trs.length; ++j)
- if (trs[j]['rowId'] == rowId) {
- tr_found = true;
- if (rowPos == j)
- break;
- trs[j].inject(trs[rowPos], 'before');
- const tmpTr = trs[j];
- trs.splice(j, 1);
- trs.splice(rowPos, 0, tmpTr);
- break;
+ getTrByRowId: function(rowId) {
+ const trs = this.tableBody.getElements('tr');
+ for (let i = 0; i < trs.length; ++i)
+ if (trs[i].rowId == rowId)
+ return trs[i];
+ return null;
+ },
+
+ updateTable: function(fullUpdate) {
+ if (fullUpdate === undefined)
+ fullUpdate = false;
+
+ const rows = this.getFilteredAndSortedRows();
+
+ for (let i = 0; i < this.selectedRows.length; ++i)
+ if (!(this.selectedRows[i] in rows)) {
+ this.selectedRows.splice(i, 1);
+ --i;
}
- if (tr_found) // row already exists in the table
- this.updateRow(trs[rowPos], fullUpdate);
- else { // else create a new row in the table
- const tr = new Element('tr');
-
- tr['rowId'] = rows[rowPos]['rowId'];
-
- tr._this = this;
- tr.addEvent('contextmenu', function(e) {
- if (!this._this.isRowSelected(this.rowId)) {
- this._this.deselectAll();
- this._this.selectRow(this.rowId);
+
+ const trs = this.tableBody.getElements('tr');
+
+ for (let rowPos = 0; rowPos < rows.length; ++rowPos) {
+ const rowId = rows[rowPos]['rowId'];
+ let tr_found = false;
+ for (let j = rowPos; j < trs.length; ++j)
+ if (trs[j]['rowId'] == rowId) {
+ tr_found = true;
+ if (rowPos == j)
+ break;
+ trs[j].inject(trs[rowPos], 'before');
+ const tmpTr = trs[j];
+ trs.splice(j, 1);
+ trs.splice(rowPos, 0, tmpTr);
+ break;
}
- return true;
- });
- tr.addEvent('click', function(e) {
- e.stop();
- if (e.control || e.meta) {
- // CTRL/CMD ⌘ key was pressed
- if (this._this.isRowSelected(this.rowId))
- this._this.deselectRow(this.rowId);
- else
+ if (tr_found) // row already exists in the table
+ this.updateRow(trs[rowPos], fullUpdate);
+ else { // else create a new row in the table
+ const tr = new Element('tr');
+
+ tr['rowId'] = rows[rowPos]['rowId'];
+
+ tr._this = this;
+ tr.addEvent('contextmenu', function(e) {
+ if (!this._this.isRowSelected(this.rowId)) {
+ this._this.deselectAll();
+ this._this.selectRow(this.rowId);
+ }
+ return true;
+ });
+ tr.addEvent('click', function(e) {
+ e.stop();
+ if (e.control || e.meta) {
+ // CTRL/CMD ⌘ key was pressed
+ if (this._this.isRowSelected(this.rowId))
+ this._this.deselectRow(this.rowId);
+ else
+ this._this.selectRow(this.rowId);
+ }
+ else if (e.shift && (this._this.selectedRows.length == 1)) {
+ // Shift key was pressed
+ this._this.selectRows(this._this.getSelectedRowId(), this.rowId);
+ }
+ else {
+ // Simple selection
+ this._this.deselectAll();
+ this._this.selectRow(this.rowId);
+ }
+ return false;
+ });
+ tr.addEvent('touchstart', function(e) {
+ if (!this._this.isRowSelected(this.rowId)) {
+ this._this.deselectAll();
this._this.selectRow(this.rowId);
+ }
+ return false;
+ });
+
+ this.setupTr(tr);
+
+ for (let k = 0; k < this.columns.length; ++k) {
+ const td = new Element('td');
+ if ((this.columns[k].visible == '0') || this.columns[k].force_hide)
+ td.addClass('invisible');
+ td.injectInside(tr);
}
- else if (e.shift && (this._this.selectedRows.length == 1)) {
- // Shift key was pressed
- this._this.selectRows(this._this.getSelectedRowId(), this.rowId);
+
+ // Insert
+ if (rowPos >= trs.length) {
+ tr.inject(this.tableBody);
+ trs.push(tr);
}
else {
- // Simple selection
- this._this.deselectAll();
- this._this.selectRow(this.rowId);
+ tr.inject(trs[rowPos], 'before');
+ trs.splice(rowPos, 0, tr);
}
- return false;
- });
- tr.addEvent('touchstart', function(e) {
- if (!this._this.isRowSelected(this.rowId)) {
- this._this.deselectAll();
- this._this.selectRow(this.rowId);
+
+ // Update context menu
+ if (this.contextMenu)
+ this.contextMenu.addTarget(tr);
+
+ this.updateRow(tr, true);
+ }
+ }
+
+ let rowPos = rows.length;
+
+ while ((rowPos < trs.length) && (trs.length > 0)) {
+ trs[trs.length - 1].dispose();
+ trs.pop();
+ }
+ },
+
+ setupTr: function(tr) {},
+
+ updateRow: function(tr, fullUpdate) {
+ const row = this.rows.get(tr.rowId);
+ const data = row[fullUpdate ? 'full_data' : 'data'];
+
+ const tds = tr.getElements('td');
+ for (let i = 0; i < this.columns.length; ++i) {
+ if (data.hasOwnProperty(this.columns[i].dataProperties[0]))
+ this.columns[i].updateTd(tds[i], row);
+ }
+ row['data'] = {};
+ },
+
+ removeRow: function(rowId) {
+ this.selectedRows.erase(rowId);
+ const tr = this.getTrByRowId(rowId);
+ if (tr !== null) {
+ tr.dispose();
+ this.rows.erase(rowId);
+ return true;
+ }
+ return false;
+ },
+
+ clear: function() {
+ this.deselectAll();
+ this.rows.empty();
+ const trs = this.tableBody.getElements('tr');
+ while (trs.length > 0) {
+ trs[trs.length - 1].dispose();
+ trs.pop();
+ }
+ },
+
+ selectedRowsIds: function() {
+ return this.selectedRows.slice();
+ },
+
+ getRowIds: function() {
+ return this.rows.getKeys();
+ },
+ });
+
+ const TorrentsTable = new Class({
+ Extends: DynamicTable,
+
+ initColumns: function() {
+ this.newColumn('priority', '', '#', 30, true);
+ this.newColumn('state_icon', 'cursor: default', '', 22, true);
+ this.newColumn('name', '', 'QBT_TR(Name)QBT_TR[CONTEXT=TransferListModel]', 200, true);
+ this.newColumn('size', '', 'QBT_TR(Size)QBT_TR[CONTEXT=TransferListModel]', 100, true);
+ this.newColumn('total_size', '', 'QBT_TR(Total Size)QBT_TR[CONTEXT=TransferListModel]', 100, false);
+ this.newColumn('progress', '', 'QBT_TR(Done)QBT_TR[CONTEXT=TransferListModel]', 85, true);
+ this.newColumn('status', '', 'QBT_TR(Status)QBT_TR[CONTEXT=TransferListModel]', 100, true);
+ this.newColumn('num_seeds', '', 'QBT_TR(Seeds)QBT_TR[CONTEXT=TransferListModel]', 100, true);
+ this.newColumn('num_leechs', '', 'QBT_TR(Peers)QBT_TR[CONTEXT=TransferListModel]', 100, true);
+ this.newColumn('dlspeed', '', 'QBT_TR(Down Speed)QBT_TR[CONTEXT=TransferListModel]', 100, true);
+ this.newColumn('upspeed', '', 'QBT_TR(Up Speed)QBT_TR[CONTEXT=TransferListModel]', 100, true);
+ this.newColumn('eta', '', 'QBT_TR(ETA)QBT_TR[CONTEXT=TransferListModel]', 100, true);
+ this.newColumn('ratio', '', 'QBT_TR(Ratio)QBT_TR[CONTEXT=TransferListModel]', 100, true);
+ this.newColumn('category', '', 'QBT_TR(Category)QBT_TR[CONTEXT=TransferListModel]', 100, true);
+ this.newColumn('tags', '', 'QBT_TR(Tags)QBT_TR[CONTEXT=TransferListModel]', 100, true);
+ this.newColumn('added_on', '', 'QBT_TR(Added On)QBT_TR[CONTEXT=TransferListModel]', 100, true);
+ this.newColumn('completion_on', '', 'QBT_TR(Completed On)QBT_TR[CONTEXT=TransferListModel]', 100, false);
+ this.newColumn('tracker', '', 'QBT_TR(Tracker)QBT_TR[CONTEXT=TransferListModel]', 100, false);
+ this.newColumn('dl_limit', '', 'QBT_TR(Down Limit)QBT_TR[CONTEXT=TransferListModel]', 100, false);
+ this.newColumn('up_limit', '', 'QBT_TR(Up Limit)QBT_TR[CONTEXT=TransferListModel]', 100, false);
+ this.newColumn('downloaded', '', 'QBT_TR(Downloaded)QBT_TR[CONTEXT=TransferListModel]', 100, false);
+ this.newColumn('uploaded', '', 'QBT_TR(Uploaded)QBT_TR[CONTEXT=TransferListModel]', 100, false);
+ this.newColumn('downloaded_session', '', 'QBT_TR(Session Download)QBT_TR[CONTEXT=TransferListModel]', 100, false);
+ this.newColumn('uploaded_session', '', 'QBT_TR(Session Upload)QBT_TR[CONTEXT=TransferListModel]', 100, false);
+ this.newColumn('amount_left', '', 'QBT_TR(Remaining)QBT_TR[CONTEXT=TransferListModel]', 100, false);
+ this.newColumn('time_active', '', 'QBT_TR(Time Active)QBT_TR[CONTEXT=TransferListModel]', 100, false);
+ this.newColumn('save_path', '', 'QBT_TR(Save path)QBT_TR[CONTEXT=TransferListModel]', 100, false);
+ this.newColumn('completed', '', 'QBT_TR(Completed)QBT_TR[CONTEXT=TransferListModel]', 100, false);
+ this.newColumn('max_ratio', '', 'QBT_TR(Ratio Limit)QBT_TR[CONTEXT=TransferListModel]', 100, false);
+ this.newColumn('seen_complete', '', 'QBT_TR(Last Seen Complete)QBT_TR[CONTEXT=TransferListModel]', 100, false);
+ this.newColumn('last_activity', '', 'QBT_TR(Last Activity)QBT_TR[CONTEXT=TransferListModel]', 100, false);
+ this.newColumn('availability', '', 'QBT_TR(Availability)QBT_TR[CONTEXT=TransferListModel]', 100, false);
+
+ this.columns['state_icon'].onclick = '';
+ this.columns['state_icon'].dataProperties[0] = 'state';
+
+ this.columns['num_seeds'].dataProperties.push('num_complete');
+ this.columns['num_leechs'].dataProperties.push('num_incomplete');
+
+ this.initColumnsFunctions();
+ },
+
+ initColumnsFunctions: function() {
+
+ // state_icon
+ this.columns['state_icon'].updateTd = function(td, row) {
+ let state = this.getRowValue(row);
+ // normalize states
+ switch (state) {
+ case "forcedDL":
+ case "metaDL":
+ state = "downloading";
+ break;
+ case "allocating":
+ state = "stalledDL";
+ break;
+ case "forcedUP":
+ state = "uploading";
+ break;
+ case "pausedDL":
+ state = "paused";
+ break;
+ case "pausedUP":
+ state = "completed";
+ break;
+ case "queuedDL":
+ case "queuedUP":
+ state = "queued";
+ break;
+ case "checkingDL":
+ case "checkingUP":
+ case "queuedForChecking":
+ case "checkingResumeData":
+ case "moving":
+ state = "checking";
+ break;
+ case "unknown":
+ case "missingFiles":
+ state = "error";
+ break;
+ default:
+ break; // do nothing
+ }
+
+ const img_path = 'images/skin/' + state + '.svg';
+
+ if (td.getChildren('img').length > 0) {
+ const img = td.getChildren('img')[0];
+ if (img.src.indexOf(img_path) < 0) {
+ img.set('src', img_path);
+ img.set('title', state);
}
- return false;
- });
+ }
+ else {
+ td.adopt(new Element('img', {
+ 'src': img_path,
+ 'class': 'stateIcon',
+ 'title': state
+ }));
+ }
+ };
- this.setupTr(tr);
+ // status
+ this.columns['status'].updateTd = function(td, row) {
+ const state = this.getRowValue(row);
+ if (!state) return;
- for (let k = 0; k < this.columns.length; ++k) {
- const td = new Element('td');
- if ((this.columns[k].visible == '0') || this.columns[k].force_hide)
- td.addClass('invisible');
- td.injectInside(tr);
+ let status;
+ switch (state) {
+ case "downloading":
+ status = "QBT_TR(Downloading)QBT_TR[CONTEXT=TransferListDelegate]";
+ break;
+ case "stalledDL":
+ status = "QBT_TR(Stalled)QBT_TR[CONTEXT=TransferListDelegate]";
+ break;
+ case "metaDL":
+ status = "QBT_TR(Downloading metadata)QBT_TR[CONTEXT=TransferListDelegate]";
+ break;
+ case "forcedDL":
+ status = "QBT_TR([F] Downloading)QBT_TR[CONTEXT=TransferListDelegate]";
+ break;
+ case "allocating":
+ status = "QBT_TR(Allocating)QBT_TR[CONTEXT=TransferListDelegate]";
+ break;
+ case "uploading":
+ case "stalledUP":
+ status = "QBT_TR(Seeding)QBT_TR[CONTEXT=TransferListDelegate]";
+ break;
+ case "forcedUP":
+ status = "QBT_TR([F] Seeding)QBT_TR[CONTEXT=TransferListDelegate]";
+ break;
+ case "queuedDL":
+ case "queuedUP":
+ status = "QBT_TR(Queued)QBT_TR[CONTEXT=TransferListDelegate]";
+ break;
+ case "checkingDL":
+ case "checkingUP":
+ status = "QBT_TR(Checking)QBT_TR[CONTEXT=TransferListDelegate]";
+ break;
+ case "queuedForChecking":
+ status = "QBT_TR(Queued for checking)QBT_TR[CONTEXT=TransferListDelegate]";
+ break;
+ case "checkingResumeData":
+ status = "QBT_TR(Checking resume data)QBT_TR[CONTEXT=TransferListDelegate]";
+ break;
+ case "pausedDL":
+ status = "QBT_TR(Paused)QBT_TR[CONTEXT=TransferListDelegate]";
+ break;
+ case "pausedUP":
+ status = "QBT_TR(Completed)QBT_TR[CONTEXT=TransferListDelegate]";
+ break;
+ case "moving":
+ status = "QBT_TR(Moving)QBT_TR[CONTEXT=TransferListDelegate]";
+ break;
+ case "missingFiles":
+ status = "QBT_TR(Missing Files)QBT_TR[CONTEXT=TransferListDelegate]";
+ break;
+ case "error":
+ status = "QBT_TR(Errored)QBT_TR[CONTEXT=TransferListDelegate]";
+ break;
+ default:
+ status = "QBT_TR(Unknown)QBT_TR[CONTEXT=HttpServer]";
}
- // Insert
- if (rowPos >= trs.length) {
- tr.inject(this.tableBody);
- trs.push(tr);
+ td.set('html', status);
+ td.set('title', status);
+ };
+
+ // priority
+ this.columns['priority'].updateTd = function(td, row) {
+ const queuePos = this.getRowValue(row);
+ const formattedQueuePos = (queuePos < 1) ? '*' : queuePos;
+ td.set('html', formattedQueuePos);
+ td.set('title', formattedQueuePos);
+ };
+
+ this.columns['priority'].compareRows = function(row1, row2) {
+ let row1_val = this.getRowValue(row1);
+ let row2_val = this.getRowValue(row2);
+ if (row1_val < 1)
+ row1_val = 1000000;
+ if (row2_val < 1)
+ row2_val = 1000000;
+ if (row1_val < row2_val)
+ return -1;
+ else if (row1_val > row2_val)
+ return 1;
+ else return 0;
+ };
+
+ // name, category, tags
+ this.columns['name'].updateTd = function(td, row) {
+ const name = window.qBittorrent.Misc.escapeHtml(this.getRowValue(row))
+ td.set('html', name);
+ td.set('title', name);
+ };
+ this.columns['category'].updateTd = this.columns['name'].updateTd;
+ this.columns['tags'].updateTd = this.columns['name'].updateTd;
+
+ this.columns['name'].compareRows = function(row1, row2) {
+ const row1Val = this.getRowValue(row1);
+ const row2Val = this.getRowValue(row2);
+ return row1Val.localeCompare(row2Val, undefined, {numeric: true, sensitivity: 'base'});
+ };
+ this.columns['category'].compareRows = this.columns['name'].compareRows;
+ this.columns['tags'].compareRows = this.columns['name'].compareRows;
+
+ // size
+ this.columns['size'].updateTd = function(td, row) {
+ const size = window.qBittorrent.Misc.friendlyUnit(this.getRowValue(row), false);
+ td.set('html', size);
+ td.set('title', size);
+ };
+
+ // progress
+ this.columns['progress'].updateTd = function(td, row) {
+ const progress = this.getRowValue(row);
+ let progressFormated = (progress * 100).round(1);
+ if (progressFormated == 100.0 && progress != 1.0)
+ progressFormated = 99.9;
+
+ if (td.getChildren('div').length > 0) {
+ const div = td.getChildren('div')[0];
+ if (td.resized) {
+ td.resized = false;
+ div.setWidth(ProgressColumnWidth - 5);
+ }
+ if (div.getValue() != progressFormated)
+ div.setValue(progressFormated);
}
else {
- tr.inject(trs[rowPos], 'before');
- trs.splice(rowPos, 0, tr);
+ if (ProgressColumnWidth < 0)
+ ProgressColumnWidth = td.offsetWidth;
+ td.adopt(new window.qBittorrent.ProgressBar.ProgressBar(progressFormated.toFloat(), {
+ 'width': ProgressColumnWidth - 5
+ }));
+ td.resized = false;
}
+ };
- // Update context menu
- if (this.contextMenu)
- this.contextMenu.addTarget(tr);
+ this.columns['progress'].onResize = function(columnName) {
+ const pos = this.getColumnPos(columnName);
+ const trs = this.tableBody.getElements('tr');
+ ProgressColumnWidth = -1;
+ for (let i = 0; i < trs.length; ++i) {
+ const td = trs[i].getElements('td')[pos];
+ if (ProgressColumnWidth < 0)
+ ProgressColumnWidth = td.offsetWidth;
+ td.resized = true;
+ this.columns[columnName].updateTd(td, this.rows.get(trs[i].rowId));
+ }
+ }.bind(this);
- this.updateRow(tr, true);
- }
- }
+ // num_seeds
+ this.columns['num_seeds'].updateTd = function(td, row) {
+ const num_seeds = this.getRowValue(row, 0);
+ const num_complete = this.getRowValue(row, 1);
+ let html = num_seeds;
+ if (num_complete != -1)
+ html += ' (' + num_complete + ')';
+ td.set('html', html);
+ td.set('title', html);
+ };
+ this.columns['num_seeds'].compareRows = function(row1, row2) {
+ const num_seeds1 = this.getRowValue(row1, 0);
+ const num_complete1 = this.getRowValue(row1, 1);
- let rowPos = rows.length;
+ const num_seeds2 = this.getRowValue(row2, 0);
+ const num_complete2 = this.getRowValue(row2, 1);
- while ((rowPos < trs.length) && (trs.length > 0)) {
- trs[trs.length - 1].dispose();
- trs.pop();
- }
- },
+ if (num_complete1 < num_complete2)
+ return -1;
+ else if (num_complete1 > num_complete2)
+ return 1;
+ else if (num_seeds1 < num_seeds2)
+ return -1;
+ else if (num_seeds1 > num_seeds2)
+ return 1;
+ else return 0;
+ };
- setupTr: function(tr) {},
+ // num_leechs
+ this.columns['num_leechs'].updateTd = this.columns['num_seeds'].updateTd;
+ this.columns['num_leechs'].compareRows = this.columns['num_seeds'].compareRows;
- updateRow: function(tr, fullUpdate) {
- const row = this.rows.get(tr.rowId);
- const data = row[fullUpdate ? 'full_data' : 'data'];
+ // dlspeed
+ this.columns['dlspeed'].updateTd = function(td, row) {
+ const speed = window.qBittorrent.Misc.friendlyUnit(this.getRowValue(row), true);
+ td.set('html', speed);
+ td.set('title', speed);
+ };
- const tds = tr.getElements('td');
- for (let i = 0; i < this.columns.length; ++i) {
- if (data.hasOwnProperty(this.columns[i].dataProperties[0]))
- this.columns[i].updateTd(tds[i], row);
- }
- row['data'] = {};
- },
-
- removeRow: function(rowId) {
- this.selectedRows.erase(rowId);
- const tr = this.getTrByRowId(rowId);
- if (tr !== null) {
- tr.dispose();
- this.rows.erase(rowId);
- return true;
- }
- return false;
- },
-
- clear: function() {
- this.deselectAll();
- this.rows.empty();
- const trs = this.tableBody.getElements('tr');
- while (trs.length > 0) {
- trs[trs.length - 1].dispose();
- trs.pop();
- }
- },
-
- selectedRowsIds: function() {
- return this.selectedRows.slice();
- },
-
- getRowIds: function() {
- return this.rows.getKeys();
- },
-});
-
-const TorrentsTable = new Class({
- Extends: DynamicTable,
-
- initColumns: function() {
- this.newColumn('priority', '', '#', 30, true);
- this.newColumn('state_icon', 'cursor: default', '', 22, true);
- this.newColumn('name', '', 'QBT_TR(Name)QBT_TR[CONTEXT=TransferListModel]', 200, true);
- this.newColumn('size', '', 'QBT_TR(Size)QBT_TR[CONTEXT=TransferListModel]', 100, true);
- this.newColumn('total_size', '', 'QBT_TR(Total Size)QBT_TR[CONTEXT=TransferListModel]', 100, false);
- this.newColumn('progress', '', 'QBT_TR(Done)QBT_TR[CONTEXT=TransferListModel]', 85, true);
- this.newColumn('status', '', 'QBT_TR(Status)QBT_TR[CONTEXT=TransferListModel]', 100, true);
- this.newColumn('num_seeds', '', 'QBT_TR(Seeds)QBT_TR[CONTEXT=TransferListModel]', 100, true);
- this.newColumn('num_leechs', '', 'QBT_TR(Peers)QBT_TR[CONTEXT=TransferListModel]', 100, true);
- this.newColumn('dlspeed', '', 'QBT_TR(Down Speed)QBT_TR[CONTEXT=TransferListModel]', 100, true);
- this.newColumn('upspeed', '', 'QBT_TR(Up Speed)QBT_TR[CONTEXT=TransferListModel]', 100, true);
- this.newColumn('eta', '', 'QBT_TR(ETA)QBT_TR[CONTEXT=TransferListModel]', 100, true);
- this.newColumn('ratio', '', 'QBT_TR(Ratio)QBT_TR[CONTEXT=TransferListModel]', 100, true);
- this.newColumn('category', '', 'QBT_TR(Category)QBT_TR[CONTEXT=TransferListModel]', 100, true);
- this.newColumn('tags', '', 'QBT_TR(Tags)QBT_TR[CONTEXT=TransferListModel]', 100, true);
- this.newColumn('added_on', '', 'QBT_TR(Added On)QBT_TR[CONTEXT=TransferListModel]', 100, true);
- this.newColumn('completion_on', '', 'QBT_TR(Completed On)QBT_TR[CONTEXT=TransferListModel]', 100, false);
- this.newColumn('tracker', '', 'QBT_TR(Tracker)QBT_TR[CONTEXT=TransferListModel]', 100, false);
- this.newColumn('dl_limit', '', 'QBT_TR(Down Limit)QBT_TR[CONTEXT=TransferListModel]', 100, false);
- this.newColumn('up_limit', '', 'QBT_TR(Up Limit)QBT_TR[CONTEXT=TransferListModel]', 100, false);
- this.newColumn('downloaded', '', 'QBT_TR(Downloaded)QBT_TR[CONTEXT=TransferListModel]', 100, false);
- this.newColumn('uploaded', '', 'QBT_TR(Uploaded)QBT_TR[CONTEXT=TransferListModel]', 100, false);
- this.newColumn('downloaded_session', '', 'QBT_TR(Session Download)QBT_TR[CONTEXT=TransferListModel]', 100, false);
- this.newColumn('uploaded_session', '', 'QBT_TR(Session Upload)QBT_TR[CONTEXT=TransferListModel]', 100, false);
- this.newColumn('amount_left', '', 'QBT_TR(Remaining)QBT_TR[CONTEXT=TransferListModel]', 100, false);
- this.newColumn('time_active', '', 'QBT_TR(Time Active)QBT_TR[CONTEXT=TransferListModel]', 100, false);
- this.newColumn('save_path', '', 'QBT_TR(Save path)QBT_TR[CONTEXT=TransferListModel]', 100, false);
- this.newColumn('completed', '', 'QBT_TR(Completed)QBT_TR[CONTEXT=TransferListModel]', 100, false);
- this.newColumn('max_ratio', '', 'QBT_TR(Ratio Limit)QBT_TR[CONTEXT=TransferListModel]', 100, false);
- this.newColumn('seen_complete', '', 'QBT_TR(Last Seen Complete)QBT_TR[CONTEXT=TransferListModel]', 100, false);
- this.newColumn('last_activity', '', 'QBT_TR(Last Activity)QBT_TR[CONTEXT=TransferListModel]', 100, false);
- this.newColumn('availability', '', 'QBT_TR(Availability)QBT_TR[CONTEXT=TransferListModel]', 100, false);
-
- this.columns['state_icon'].onclick = '';
- this.columns['state_icon'].dataProperties[0] = 'state';
-
- this.columns['num_seeds'].dataProperties.push('num_complete');
- this.columns['num_leechs'].dataProperties.push('num_incomplete');
-
- this.initColumnsFunctions();
- },
-
- initColumnsFunctions: function() {
-
- // state_icon
- this.columns['state_icon'].updateTd = function(td, row) {
- let state = this.getRowValue(row);
- // normalize states
- switch (state) {
- case "forcedDL":
- case "metaDL":
- state = "downloading";
- break;
- case "allocating":
- state = "stalledDL";
- break;
- case "forcedUP":
- state = "uploading";
- break;
- case "pausedDL":
- state = "paused";
- break;
- case "pausedUP":
- state = "completed";
- break;
- case "queuedDL":
- case "queuedUP":
- state = "queued";
- break;
- case "checkingDL":
- case "checkingUP":
- case "queuedForChecking":
- case "checkingResumeData":
- case "moving":
- state = "checking";
- break;
- case "unknown":
- case "missingFiles":
- state = "error";
- break;
- default:
- break; // do nothing
- }
+ // upspeed
+ this.columns['upspeed'].updateTd = this.columns['dlspeed'].updateTd;
- const img_path = 'images/skin/' + state + '.svg';
+ // eta
+ this.columns['eta'].updateTd = function(td, row) {
+ const eta = window.qBittorrent.Misc.friendlyDuration(this.getRowValue(row));
+ td.set('html', eta);
+ td.set('title', eta);
+ };
- if (td.getChildren('img').length > 0) {
- const img = td.getChildren('img')[0];
- if (img.src.indexOf(img_path) < 0) {
- img.set('src', img_path);
- img.set('title', state);
+ // ratio
+ this.columns['ratio'].updateTd = function(td, row) {
+ const ratio = this.getRowValue(row);
+ const string = (ratio === -1) ? '∞' : window.qBittorrent.Misc.toFixedPointString(ratio, 2);
+ td.set('html', string);
+ td.set('title', string);
+ };
+
+ // added on
+ this.columns['added_on'].updateTd = function(td, row) {
+ const date = new Date(this.getRowValue(row) * 1000).toLocaleString();
+ td.set('html', date);
+ td.set('title', date);
+ };
+
+ // completion_on
+ this.columns['completion_on'].updateTd = function(td, row) {
+ const val = this.getRowValue(row);
+ if ((val === 0xffffffff) || (val < 0)) {
+ td.set('html', '');
+ td.set('title', '');
}
- }
- else {
- td.adopt(new Element('img', {
- 'src': img_path,
- 'class': 'stateIcon',
- 'title': state
- }));
- }
- };
+ else {
+ const date = new Date(this.getRowValue(row) * 1000).toLocaleString();
+ td.set('html', date);
+ td.set('title', date);
+ }
+ };
+
+ // seen_complete
+ this.columns['seen_complete'].updateTd = this.columns['completion_on'].updateTd;
+
+ // dl_limit, up_limit
+ this.columns['dl_limit'].updateTd = function(td, row) {
+ const speed = this.getRowValue(row);
+ if (speed === 0) {
+ td.set('html', '∞');
+ td.set('title', '∞');
+ }
+ else {
+ const formattedSpeed = window.qBittorrent.Misc.friendlyUnit(speed, true);
+ td.set('html', formattedSpeed);
+ td.set('title', formattedSpeed);
+ }
+ };
+
+ this.columns['up_limit'].updateTd = this.columns['dl_limit'].updateTd;
+
+ // downloaded, uploaded, downloaded_session, uploaded_session, amount_left, completed, total_size
+ this.columns['downloaded'].updateTd = this.columns['size'].updateTd;
+ this.columns['uploaded'].updateTd = this.columns['size'].updateTd;
+ this.columns['downloaded_session'].updateTd = this.columns['size'].updateTd;
+ this.columns['uploaded_session'].updateTd = this.columns['size'].updateTd;
+ this.columns['amount_left'].updateTd = this.columns['size'].updateTd;
+ this.columns['amount_left'].updateTd = this.columns['size'].updateTd;
+ this.columns['completed'].updateTd = this.columns['size'].updateTd;
+ this.columns['total_size'].updateTd = this.columns['size'].updateTd;
+
+ // save_path, tracker
+ this.columns['save_path'].updateTd = this.columns['name'].updateTd;
+ this.columns['tracker'].updateTd = this.columns['name'].updateTd;
+
+ // max_ratio
+ this.columns['max_ratio'].updateTd = this.columns['ratio'].updateTd;
+
+ // last_activity
+ this.columns['last_activity'].updateTd = function(td, row) {
+ const val = this.getRowValue(row);
+ if (val < 1) {
+ td.set('html', '∞');
+ td.set('title', '∞');
+ }
+ else {
+ const formattedVal = 'QBT_TR(%1 ago)QBT_TR[CONTEXT=TransferListDelegate]'.replace('%1', window.qBittorrent.Misc.friendlyDuration((new Date()) / 1000 - val));
+ td.set('html', formattedVal);
+ td.set('title', formattedVal);
+ }
+ };
+
+ // time active
+ this.columns['time_active'].updateTd = function(td, row) {
+ const time = window.qBittorrent.Misc.friendlyDuration(this.getRowValue(row));
+ td.set('html', time);
+ td.set('title', time);
+ };
+
+ // availability
+ this.columns['availability'].updateTd = function(td, row) {
+ const value = window.qBittorrent.Misc.toFixedPointString(this.getRowValue(row), 3);
+ td.set('html', value);
+ td.set('title', value);
+ };
+ },
- // status
- this.columns['status'].updateTd = function(td, row) {
- const state = this.getRowValue(row);
- if (!state) return;
+ applyFilter: function(row, filterName, categoryHash, tagHash, filterTerms) {
+ const state = row['full_data'].state;
+ const name = row['full_data'].name.toLowerCase();
+ let inactive = false;
+ let r;
- let status;
- switch (state) {
- case "downloading":
- status = "QBT_TR(Downloading)QBT_TR[CONTEXT=TransferListDelegate]";
- break;
- case "stalledDL":
- status = "QBT_TR(Stalled)QBT_TR[CONTEXT=TransferListDelegate]";
- break;
- case "metaDL":
- status = "QBT_TR(Downloading metadata)QBT_TR[CONTEXT=TransferListDelegate]";
- break;
- case "forcedDL":
- status = "QBT_TR([F] Downloading)QBT_TR[CONTEXT=TransferListDelegate]";
- break;
- case "allocating":
- status = "QBT_TR(Allocating)QBT_TR[CONTEXT=TransferListDelegate]";
- break;
- case "uploading":
- case "stalledUP":
- status = "QBT_TR(Seeding)QBT_TR[CONTEXT=TransferListDelegate]";
- break;
- case "forcedUP":
- status = "QBT_TR([F] Seeding)QBT_TR[CONTEXT=TransferListDelegate]";
- break;
- case "queuedDL":
- case "queuedUP":
- status = "QBT_TR(Queued)QBT_TR[CONTEXT=TransferListDelegate]";
- break;
- case "checkingDL":
- case "checkingUP":
- status = "QBT_TR(Checking)QBT_TR[CONTEXT=TransferListDelegate]";
- break;
- case "queuedForChecking":
- status = "QBT_TR(Queued for checking)QBT_TR[CONTEXT=TransferListDelegate]";
+ switch (filterName) {
+ case 'downloading':
+ if (state != 'downloading' && !~state.indexOf('DL'))
+ return false;
break;
- case "checkingResumeData":
- status = "QBT_TR(Checking resume data)QBT_TR[CONTEXT=TransferListDelegate]";
+ case 'seeding':
+ if (state != 'uploading' && state != 'forcedUP' && state != 'stalledUP' && state != 'queuedUP' && state != 'checkingUP')
+ return false;
break;
- case "pausedDL":
- status = "QBT_TR(Paused)QBT_TR[CONTEXT=TransferListDelegate]";
+ case 'completed':
+ if (state != 'uploading' && !~state.indexOf('UP'))
+ return false;
break;
- case "pausedUP":
- status = "QBT_TR(Completed)QBT_TR[CONTEXT=TransferListDelegate]";
+ case 'paused':
+ if (!~state.indexOf('paused'))
+ return false;
break;
- case "moving":
- status = "QBT_TR(Moving)QBT_TR[CONTEXT=TransferListDelegate]";
+ case 'resumed':
+ if (~state.indexOf('paused'))
+ return false;
break;
- case "missingFiles":
- status = "QBT_TR(Missing Files)QBT_TR[CONTEXT=TransferListDelegate]";
+ case 'inactive':
+ inactive = true;
+ // fallthrough
+ case 'active':
+ if (state == 'stalledDL')
+ r = (row['full_data'].upspeed > 0);
+ else
+ r = state == 'metaDL' || state == 'downloading' || state == 'forcedDL' || state == 'uploading' || state == 'forcedUP';
+ if (r == inactive)
+ return false;
break;
- case "error":
- status = "QBT_TR(Errored)QBT_TR[CONTEXT=TransferListDelegate]";
+ case 'errored':
+ if (state != 'error' && state != "unknown" && state != "missingFiles")
+ return false;
break;
- default:
- status = "QBT_TR(Unknown)QBT_TR[CONTEXT=HttpServer]";
}
- td.set('html', status);
- td.set('title', status);
- };
-
- // priority
- this.columns['priority'].updateTd = function(td, row) {
- const queuePos = this.getRowValue(row);
- const formattedQueuePos = (queuePos < 1) ? '*' : queuePos;
- td.set('html', formattedQueuePos);
- td.set('title', formattedQueuePos);
- };
-
- this.columns['priority'].compareRows = function(row1, row2) {
- let row1_val = this.getRowValue(row1);
- let row2_val = this.getRowValue(row2);
- if (row1_val < 1)
- row1_val = 1000000;
- if (row2_val < 1)
- row2_val = 1000000;
- if (row1_val < row2_val)
- return -1;
- else if (row1_val > row2_val)
- return 1;
- else return 0;
- };
-
- // name, category, tags
- this.columns['name'].updateTd = function(td, row) {
- const name = escapeHtml(this.getRowValue(row))
- td.set('html', name);
- td.set('title', name);
- };
- this.columns['category'].updateTd = this.columns['name'].updateTd;
- this.columns['tags'].updateTd = this.columns['name'].updateTd;
-
- this.columns['name'].compareRows = function(row1, row2) {
- const row1Val = this.getRowValue(row1);
- const row2Val = this.getRowValue(row2);
- return row1Val.localeCompare(row2Val, undefined, {numeric: true, sensitivity: 'base'});
- };
- this.columns['category'].compareRows = this.columns['name'].compareRows;
- this.columns['tags'].compareRows = this.columns['name'].compareRows;
-
- // size
- this.columns['size'].updateTd = function(td, row) {
- const size = friendlyUnit(this.getRowValue(row), false);
- td.set('html', size);
- td.set('title', size);
- };
-
- // progress
- this.columns['progress'].updateTd = function(td, row) {
- const progress = this.getRowValue(row);
- let progressFormated = (progress * 100).round(1);
- if (progressFormated == 100.0 && progress != 1.0)
- progressFormated = 99.9;
-
- if (td.getChildren('div').length > 0) {
- const div = td.getChildren('div')[0];
- if (td.resized) {
- td.resized = false;
- div.setWidth(ProgressColumnWidth - 5);
+ const categoryHashInt = parseInt(categoryHash);
+ if (!isNaN(categoryHashInt)) {
+ switch (categoryHashInt) {
+ case CATEGORIES_ALL:
+ break; // do nothing
+ case CATEGORIES_UNCATEGORIZED:
+ if (row['full_data'].category.length !== 0)
+ return false;
+ break; // do nothing
+ default:
+ if (categoryHashInt !== genHash(row['full_data'].category))
+ return false;
}
- if (div.getValue() != progressFormated)
- div.setValue(progressFormated);
- }
- else {
- if (ProgressColumnWidth < 0)
- ProgressColumnWidth = td.offsetWidth;
- td.adopt(new ProgressBar(progressFormated.toFloat(), {
- 'width': ProgressColumnWidth - 5
- }));
- td.resized = false;
}
- };
- this.columns['progress'].onResize = function(columnName) {
- const pos = this.getColumnPos(columnName);
- const trs = this.tableBody.getElements('tr');
- ProgressColumnWidth = -1;
- for (let i = 0; i < trs.length; ++i) {
- const td = trs[i].getElements('td')[pos];
- if (ProgressColumnWidth < 0)
- ProgressColumnWidth = td.offsetWidth;
- td.resized = true;
- this.columns[columnName].updateTd(td, this.rows.get(trs[i].rowId));
+ const tagHashInt = parseInt(tagHash);
+ const isNumber = !isNaN(tagHashInt);
+ if (isNumber) {
+ switch (tagHashInt) {
+ case TAGS_ALL:
+ break; // do nothing
+
+ case TAGS_UNTAGGED:
+ if (row['full_data'].tags.length !== 0)
+ return false;
+ break; // do nothing
+
+ default:
+ let rowTags = row['full_data'].tags.split(', ');
+ rowTags = rowTags.map(function(tag) {
+ return genHash(tag);
+ });
+ if (!rowTags.contains(tagHashInt))
+ return false;
+ }
}
- }.bind(this);
-
- // num_seeds
- this.columns['num_seeds'].updateTd = function(td, row) {
- const num_seeds = this.getRowValue(row, 0);
- const num_complete = this.getRowValue(row, 1);
- let html = num_seeds;
- if (num_complete != -1)
- html += ' (' + num_complete + ')';
- td.set('html', html);
- td.set('title', html);
- };
- this.columns['num_seeds'].compareRows = function(row1, row2) {
- const num_seeds1 = this.getRowValue(row1, 0);
- const num_complete1 = this.getRowValue(row1, 1);
-
- const num_seeds2 = this.getRowValue(row2, 0);
- const num_complete2 = this.getRowValue(row2, 1);
-
- if (num_complete1 < num_complete2)
- return -1;
- else if (num_complete1 > num_complete2)
- return 1;
- else if (num_seeds1 < num_seeds2)
- return -1;
- else if (num_seeds1 > num_seeds2)
- return 1;
- else return 0;
- };
- // num_leechs
- this.columns['num_leechs'].updateTd = this.columns['num_seeds'].updateTd;
- this.columns['num_leechs'].compareRows = this.columns['num_seeds'].compareRows;
+ if ((filterTerms !== undefined) && (filterTerms !== null)
+ && (filterTerms.length > 0) && !window.qBittorrent.Misc.containsAllTerms(name, filterTerms))
+ return false;
- // dlspeed
- this.columns['dlspeed'].updateTd = function(td, row) {
- const speed = friendlyUnit(this.getRowValue(row), true);
- td.set('html', speed);
- td.set('title', speed);
- };
+ return true;
+ },
- // upspeed
- this.columns['upspeed'].updateTd = this.columns['dlspeed'].updateTd;
+ getFilteredTorrentsNumber: function(filterName, categoryHash, tagHash) {
+ let cnt = 0;
+ const rows = this.rows.getValues();
- // eta
- this.columns['eta'].updateTd = function(td, row) {
- const eta = friendlyDuration(this.getRowValue(row));
- td.set('html', eta);
- td.set('title', eta);
- };
+ for (let i = 0; i < rows.length; ++i)
+ if (this.applyFilter(rows[i], filterName, categoryHash, tagHash, null)) ++cnt;
+ return cnt;
+ },
- // ratio
- this.columns['ratio'].updateTd = function(td, row) {
- const ratio = this.getRowValue(row);
- const string = (ratio === -1) ? '∞' : toFixedPointString(ratio, 2);
- td.set('html', string);
- td.set('title', string);
- };
+ getFilteredTorrentsHashes: function(filterName, categoryHash, tagHash) {
+ const rowsHashes = [];
+ const rows = this.rows.getValues();
- // added on
- this.columns['added_on'].updateTd = function(td, row) {
- const date = new Date(this.getRowValue(row) * 1000).toLocaleString();
- td.set('html', date);
- td.set('title', date);
- };
+ for (let i = 0; i < rows.length; ++i)
+ if (this.applyFilter(rows[i], filterName, categoryHash, tagHash, null))
+ rowsHashes.push(rows[i]['rowId']);
- // completion_on
- this.columns['completion_on'].updateTd = function(td, row) {
- const val = this.getRowValue(row);
- if ((val === 0xffffffff) || (val < 0)) {
- td.set('html', '');
- td.set('title', '');
- }
- else {
- const date = new Date(this.getRowValue(row) * 1000).toLocaleString();
- td.set('html', date);
- td.set('title', date);
- }
- };
+ return rowsHashes;
+ },
- // seen_complete
- this.columns['seen_complete'].updateTd = this.columns['completion_on'].updateTd;
+ getFilteredAndSortedRows: function() {
+ const filteredRows = [];
- // dl_limit, up_limit
- this.columns['dl_limit'].updateTd = function(td, row) {
- const speed = this.getRowValue(row);
- if (speed === 0) {
- td.set('html', '∞');
- td.set('title', '∞');
- }
- else {
- const formattedSpeed = friendlyUnit(speed, true);
- td.set('html', formattedSpeed);
- td.set('title', formattedSpeed);
- }
- };
+ const rows = this.rows.getValues();
+ const filterText = $('torrentsFilterInput').value.trim().toLowerCase();
+ const filterTerms = (filterText.length > 0) ? filterText.split(" ") : null;
- this.columns['up_limit'].updateTd = this.columns['dl_limit'].updateTd;
-
- // downloaded, uploaded, downloaded_session, uploaded_session, amount_left, completed, total_size
- this.columns['downloaded'].updateTd = this.columns['size'].updateTd;
- this.columns['uploaded'].updateTd = this.columns['size'].updateTd;
- this.columns['downloaded_session'].updateTd = this.columns['size'].updateTd;
- this.columns['uploaded_session'].updateTd = this.columns['size'].updateTd;
- this.columns['amount_left'].updateTd = this.columns['size'].updateTd;
- this.columns['amount_left'].updateTd = this.columns['size'].updateTd;
- this.columns['completed'].updateTd = this.columns['size'].updateTd;
- this.columns['total_size'].updateTd = this.columns['size'].updateTd;
-
- // save_path, tracker
- this.columns['save_path'].updateTd = this.columns['name'].updateTd;
- this.columns['tracker'].updateTd = this.columns['name'].updateTd;
-
- // max_ratio
- this.columns['max_ratio'].updateTd = this.columns['ratio'].updateTd;
-
- // last_activity
- this.columns['last_activity'].updateTd = function(td, row) {
- const val = this.getRowValue(row);
- if (val < 1) {
- td.set('html', '∞');
- td.set('title', '∞');
- }
- else {
- const formattedVal = 'QBT_TR(%1 ago)QBT_TR[CONTEXT=TransferListDelegate]'.replace('%1', friendlyDuration((new Date()) / 1000 - val));
- td.set('html', formattedVal);
- td.set('title', formattedVal);
+ for (let i = 0; i < rows.length; ++i) {
+ if (this.applyFilter(rows[i], selected_filter, selected_category, selectedTag, filterTerms)) {
+ filteredRows.push(rows[i]);
+ filteredRows[rows[i].rowId] = rows[i];
+ }
}
- };
-
- // time active
- this.columns['time_active'].updateTd = function(td, row) {
- const time = friendlyDuration(this.getRowValue(row));
- td.set('html', time);
- td.set('title', time);
- };
- // availability
- this.columns['availability'].updateTd = function(td, row) {
- const value = toFixedPointString(this.getRowValue(row), 3);
- td.set('html', value);
- td.set('title', value);
- };
- },
-
- applyFilter: function(row, filterName, categoryHash, tagHash, filterTerms) {
- const state = row['full_data'].state;
- const name = row['full_data'].name.toLowerCase();
- let inactive = false;
- let r;
-
- switch (filterName) {
- case 'downloading':
- if (state != 'downloading' && !~state.indexOf('DL'))
- return false;
- break;
- case 'seeding':
- if (state != 'uploading' && state != 'forcedUP' && state != 'stalledUP' && state != 'queuedUP' && state != 'checkingUP')
- return false;
- break;
- case 'completed':
- if (state != 'uploading' && !~state.indexOf('UP'))
- return false;
- break;
- case 'paused':
- if (!~state.indexOf('paused'))
- return false;
- break;
- case 'resumed':
+ filteredRows.sort(function(row1, row2) {
+ const column = this.columns[this.sortedColumn];
+ const res = column.compareRows(row1, row2);
+ if (this.reverseSort === '0')
+ return res;
+ else
+ return -res;
+ }.bind(this));
+ return filteredRows;
+ },
+
+ setupTr: function(tr) {
+ tr.addEvent('dblclick', function(e) {
+ e.stop();
+ this._this.deselectAll();
+ this._this.selectRow(this.rowId);
+ const row = this._this.rows.get(this.rowId);
+ const state = row['full_data'].state;
if (~state.indexOf('paused'))
- return false;
- break;
- case 'inactive':
- inactive = true;
- // fallthrough
- case 'active':
- if (state == 'stalledDL')
- r = (row['full_data'].upspeed > 0);
+ startFN();
else
- r = state == 'metaDL' || state == 'downloading' || state == 'forcedDL' || state == 'uploading' || state == 'forcedUP';
- if (r == inactive)
- return false;
- break;
- case 'errored':
- if (state != 'error' && state != "unknown" && state != "missingFiles")
- return false;
- break;
- }
-
- const categoryHashInt = parseInt(categoryHash);
- if (!isNaN(categoryHashInt)) {
- switch (categoryHashInt) {
- case CATEGORIES_ALL:
- break; // do nothing
- case CATEGORIES_UNCATEGORIZED:
- if (row['full_data'].category.length !== 0)
- return false;
- break; // do nothing
- default:
- if (categoryHashInt !== genHash(row['full_data'].category))
- return false;
- }
- }
-
- const tagHashInt = parseInt(tagHash);
- const isNumber = !isNaN(tagHashInt);
- if (isNumber) {
- switch (tagHashInt) {
- case TAGS_ALL:
- break; // do nothing
+ pauseFN();
+ return true;
+ });
+ tr.addClass("torrentsTableContextMenuTarget");
+ },
- case TAGS_UNTAGGED:
- if (row['full_data'].tags.length !== 0)
- return false;
- break; // do nothing
+ getCurrentTorrentHash: function() {
+ return this.getSelectedRowId();
+ },
- default:
- let rowTags = row['full_data'].tags.split(', ');
- rowTags = rowTags.map(function(tag) {
- return genHash(tag);
- });
- if (!rowTags.contains(tagHashInt))
- return false;
- }
+ onSelectedRowChanged: function() {
+ updatePropertiesPanel();
}
+ });
+
+ const TorrentPeersTable = new Class({
+ Extends: DynamicTable,
+
+ initColumns: function() {
+ this.newColumn('country', '', 'QBT_TR(Country)QBT_TR[CONTEXT=PeerListWidget]', 22, true);
+ this.newColumn('ip', '', 'QBT_TR(IP)QBT_TR[CONTEXT=PeerListWidget]', 80, true);
+ this.newColumn('port', '', 'QBT_TR(Port)QBT_TR[CONTEXT=PeerListWidget]', 35, true);
+ this.newColumn('connection', '', 'QBT_TR(Connection)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
+ this.newColumn('flags', '', 'QBT_TR(Flags)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
+ this.newColumn('client', '', 'QBT_TR(Client)QBT_TR[CONTEXT=PeerListWidget]', 140, true);
+ this.newColumn('progress', '', 'QBT_TR(Progress)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
+ this.newColumn('dl_speed', '', 'QBT_TR(Down Speed)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
+ this.newColumn('up_speed', '', 'QBT_TR(Up Speed)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
+ this.newColumn('downloaded', '', 'QBT_TR(Downloaded)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
+ this.newColumn('uploaded', '', 'QBT_TR(Uploaded)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
+ this.newColumn('relevance', '', 'QBT_TR(Relevance)QBT_TR[CONTEXT=PeerListWidget]', 30, true);
+ this.newColumn('files', '', 'QBT_TR(Files)QBT_TR[CONTEXT=PeerListWidget]', 100, true);
+
+ this.columns['country'].dataProperties.push('country_code');
+ this.columns['flags'].dataProperties.push('flags_desc');
+ this.initColumnsFunctions();
+ },
+
+ initColumnsFunctions: function() {
+
+ // country
+
+ this.columns['country'].updateTd = function(td, row) {
+ const country = this.getRowValue(row, 0);
+ const country_code = this.getRowValue(row, 1);
+
+ if (!country_code) {
+ if (td.getChildren('img').length > 0)
+ td.getChildren('img')[0].dispose();
+ return;
+ }
- if ((filterTerms !== undefined) && (filterTerms !== null)
- && (filterTerms.length > 0) && !containsAllTerms(name, filterTerms))
- return false;
-
- return true;
- },
-
- getFilteredTorrentsNumber: function(filterName, categoryHash, tagHash) {
- let cnt = 0;
- const rows = this.rows.getValues();
+ const img_path = 'images/flags/' + country_code + '.svg';
- for (let i = 0; i < rows.length; ++i)
- if (this.applyFilter(rows[i], filterName, categoryHash, tagHash, null)) ++cnt;
- return cnt;
- },
+ if (td.getChildren('img').length > 0) {
+ const img = td.getChildren('img')[0];
+ img.set('src', img_path);
+ img.set('class', 'flags');
+ img.set('alt', country);
+ img.set('title', country);
+ }
+ else
+ td.adopt(new Element('img', {
+ 'src': img_path,
+ 'class': 'flags',
+ 'alt': country,
+ 'title': country
+ }));
+ };
- getFilteredTorrentsHashes: function(filterName, categoryHash, tagHash) {
- const rowsHashes = [];
- const rows = this.rows.getValues();
+ // ip
- for (let i = 0; i < rows.length; ++i)
- if (this.applyFilter(rows[i], filterName, categoryHash, tagHash, null))
- rowsHashes.push(rows[i]['rowId']);
+ this.columns['ip'].compareRows = function(row1, row2) {
+ const ip1 = this.getRowValue(row1);
+ const ip2 = this.getRowValue(row2);
- return rowsHashes;
- },
+ const a = ip1.split(".");
+ const b = ip2.split(".");
- getFilteredAndSortedRows: function() {
- const filteredRows = [];
+ for (let i = 0; i < 4; ++i) {
+ if (a[i] != b[i])
+ return a[i] - b[i];
+ }
- const rows = this.rows.getValues();
- const filterText = $('torrentsFilterInput').value.trim().toLowerCase();
- const filterTerms = (filterText.length > 0) ? filterText.split(" ") : null;
+ return 0;
+ };
- for (let i = 0; i < rows.length; ++i) {
- if (this.applyFilter(rows[i], selected_filter, selected_category, selectedTag, filterTerms)) {
- filteredRows.push(rows[i]);
- filteredRows[rows[i].rowId] = rows[i];
- }
- }
+ // progress, relevance
- filteredRows.sort(function(row1, row2) {
- const column = this.columns[this.sortedColumn];
- const res = column.compareRows(row1, row2);
- if (this.reverseSort === '0')
- return res;
- else
- return -res;
- }.bind(this));
- return filteredRows;
- },
-
- setupTr: function(tr) {
- tr.addEvent('dblclick', function(e) {
- e.stop();
- this._this.deselectAll();
- this._this.selectRow(this.rowId);
- const row = this._this.rows.get(this.rowId);
- const state = row['full_data'].state;
- if (~state.indexOf('paused'))
- startFN();
- else
- pauseFN();
- return true;
- });
- tr.addClass("torrentsTableContextMenuTarget");
- },
-
- getCurrentTorrentHash: function() {
- return this.getSelectedRowId();
- },
-
- onSelectedRowChanged: function() {
- updatePropertiesPanel();
- }
-});
-
-const TorrentPeersTable = new Class({
- Extends: DynamicTable,
-
- initColumns: function() {
- this.newColumn('country', '', 'QBT_TR(Country)QBT_TR[CONTEXT=PeerListWidget]', 22, true);
- this.newColumn('ip', '', 'QBT_TR(IP)QBT_TR[CONTEXT=PeerListWidget]', 80, true);
- this.newColumn('port', '', 'QBT_TR(Port)QBT_TR[CONTEXT=PeerListWidget]', 35, true);
- this.newColumn('connection', '', 'QBT_TR(Connection)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
- this.newColumn('flags', '', 'QBT_TR(Flags)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
- this.newColumn('client', '', 'QBT_TR(Client)QBT_TR[CONTEXT=PeerListWidget]', 140, true);
- this.newColumn('progress', '', 'QBT_TR(Progress)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
- this.newColumn('dl_speed', '', 'QBT_TR(Down Speed)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
- this.newColumn('up_speed', '', 'QBT_TR(Up Speed)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
- this.newColumn('downloaded', '', 'QBT_TR(Downloaded)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
- this.newColumn('uploaded', '', 'QBT_TR(Uploaded)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
- this.newColumn('relevance', '', 'QBT_TR(Relevance)QBT_TR[CONTEXT=PeerListWidget]', 30, true);
- this.newColumn('files', '', 'QBT_TR(Files)QBT_TR[CONTEXT=PeerListWidget]', 100, true);
-
- this.columns['country'].dataProperties.push('country_code');
- this.columns['flags'].dataProperties.push('flags_desc');
- this.initColumnsFunctions();
- },
-
- initColumnsFunctions: function() {
-
- // country
-
- this.columns['country'].updateTd = function(td, row) {
- const country = this.getRowValue(row, 0);
- const country_code = this.getRowValue(row, 1);
-
- if (!country_code) {
- if (td.getChildren('img').length > 0)
- td.getChildren('img')[0].dispose();
- return;
- }
+ this.columns['progress'].updateTd = function(td, row) {
+ const progress = this.getRowValue(row);
+ let progressFormated = (progress * 100).round(1);
+ if (progressFormated == 100.0 && progress != 1.0)
+ progressFormated = 99.9;
+ progressFormated += "%";
+ td.set('html', progressFormated);
+ td.set('title', progressFormated);
+ };
- const img_path = 'images/flags/' + country_code + '.svg';
+ this.columns['relevance'].updateTd = this.columns['progress'].updateTd;
- if (td.getChildren('img').length > 0) {
- const img = td.getChildren('img')[0];
- img.set('src', img_path);
- img.set('class', 'flags');
- img.set('alt', country);
- img.set('title', country);
- }
- else
- td.adopt(new Element('img', {
- 'src': img_path,
- 'class': 'flags',
- 'alt': country,
- 'title': country
- }));
- };
+ // dl_speed, up_speed
- // ip
+ this.columns['dl_speed'].updateTd = function(td, row) {
+ const speed = this.getRowValue(row);
+ if (speed === 0) {
+ td.set('html', '');
+ td.set('title', '');
+ }
+ else {
+ const formattedSpeed = window.qBittorrent.Misc.friendlyUnit(speed, true);
+ td.set('html', formattedSpeed);
+ td.set('title', formattedSpeed);
+ }
+ };
- this.columns['ip'].compareRows = function(row1, row2) {
- const ip1 = this.getRowValue(row1);
- const ip2 = this.getRowValue(row2);
+ this.columns['up_speed'].updateTd = this.columns['dl_speed'].updateTd;
- const a = ip1.split(".");
- const b = ip2.split(".");
+ // downloaded, uploaded
- for (let i = 0; i < 4; ++i) {
- if (a[i] != b[i])
- return a[i] - b[i];
- }
+ this.columns['downloaded'].updateTd = function(td, row) {
+ const downloaded = window.qBittorrent.Misc.friendlyUnit(this.getRowValue(row), false);
+ td.set('html', downloaded);
+ td.set('title', downloaded);
+ };
- return 0;
- };
+ this.columns['uploaded'].updateTd = this.columns['downloaded'].updateTd;
- // progress, relevance
+ // flags
- this.columns['progress'].updateTd = function(td, row) {
- const progress = this.getRowValue(row);
- let progressFormated = (progress * 100).round(1);
- if (progressFormated == 100.0 && progress != 1.0)
- progressFormated = 99.9;
- progressFormated += "%";
- td.set('html', progressFormated);
- td.set('title', progressFormated);
- };
+ this.columns['flags'].updateTd = function(td, row) {
+ td.innerHTML = this.getRowValue(row, 0);
+ td.title = this.getRowValue(row, 1);
+ };
- this.columns['relevance'].updateTd = this.columns['progress'].updateTd;
+ // files
- // dl_speed, up_speed
+ this.columns['files'].updateTd = function(td, row) {
+ td.innerHTML = window.qBittorrent.Misc.escapeHtml(this.getRowValue(row, 0).replace(/\n/g, ';'));
+ td.title = window.qBittorrent.Misc.escapeHtml(this.getRowValue(row, 0));
+ };
- this.columns['dl_speed'].updateTd = function(td, row) {
- const speed = this.getRowValue(row);
- if (speed === 0) {
- td.set('html', '');
- td.set('title', '');
+ }
+ });
+
+ const SearchResultsTable = new Class({
+ Extends: DynamicTable,
+
+ initColumns: function() {
+ this.newColumn('fileName', '', 'QBT_TR(Name)QBT_TR[CONTEXT=SearchResultsTable]', 500, true);
+ this.newColumn('fileSize', '', 'QBT_TR(Size)QBT_TR[CONTEXT=SearchResultsTable]', 100, true);
+ this.newColumn('nbSeeders', '', 'QBT_TR(Seeders)QBT_TR[CONTEXT=SearchResultsTable]', 100, true);
+ this.newColumn('nbLeechers', '', 'QBT_TR(Leechers)QBT_TR[CONTEXT=SearchResultsTable]', 100, true);
+ this.newColumn('siteUrl', '', 'QBT_TR(Search engine)QBT_TR[CONTEXT=SearchResultsTable]', 250, true);
+
+ this.initColumnsFunctions();
+ },
+
+ initColumnsFunctions: function() {
+ const displayText = function(td, row) {
+ const value = window.qBittorrent.Misc.escapeHtml(this.getRowValue(row));
+ td.set('html', value);
+ td.set('title', value);
}
- else {
- const formattedSpeed = friendlyUnit(speed, true);
- td.set('html', formattedSpeed);
- td.set('title', formattedSpeed);
+ const displaySize = function(td, row) {
+ const size = window.qBittorrent.Misc.friendlyUnit(this.getRowValue(row), false);
+ td.set('html', size);
+ td.set('title', size);
+ }
+ const displayNum = function(td, row) {
+ const value = window.qBittorrent.Misc.escapeHtml(this.getRowValue(row));
+ const formattedValue = (value === "-1") ? "Unknown" : value;
+ td.set('html', formattedValue);
+ td.set('title', formattedValue);
}
- };
-
- this.columns['up_speed'].updateTd = this.columns['dl_speed'].updateTd;
-
- // downloaded, uploaded
-
- this.columns['downloaded'].updateTd = function(td, row) {
- const downloaded = friendlyUnit(this.getRowValue(row), false);
- td.set('html', downloaded);
- td.set('title', downloaded);
- };
-
- this.columns['uploaded'].updateTd = this.columns['downloaded'].updateTd;
- // flags
+ this.columns['fileName'].updateTd = displayText;
+ this.columns['fileSize'].updateTd = displaySize;
+ this.columns['nbSeeders'].updateTd = displayNum;
+ this.columns['nbLeechers'].updateTd = displayNum;
+ this.columns['siteUrl'].updateTd = displayText;
+ },
+
+ getFilteredAndSortedRows: function() {
+ const getSizeFilters = function() {
+ let minSize = (window.qBittorrent.Search.searchSizeFilter.min > 0.00) ? (window.qBittorrent.Search.searchSizeFilter.min * Math.pow(1024, window.qBittorrent.Search.searchSizeFilter.minUnit)) : 0.00;
+ let maxSize = (window.qBittorrent.Search.searchSizeFilter.max > 0.00) ? (window.qBittorrent.Search.searchSizeFilter.max * Math.pow(1024, window.qBittorrent.Search.searchSizeFilter.maxUnit)) : 0.00;
+
+ if ((minSize > maxSize) && (maxSize > 0.00)) {
+ const tmp = minSize;
+ minSize = maxSize;
+ maxSize = tmp;
+ }
- this.columns['flags'].updateTd = function(td, row) {
- td.innerHTML = this.getRowValue(row, 0);
- td.title = this.getRowValue(row, 1);
- };
+ return {
+ min: minSize,
+ max: maxSize
+ }
+ };
- // files
+ const getSeedsFilters = function() {
+ let minSeeds = (window.qBittorrent.Search.searchSeedsFilter.min > 0) ? window.qBittorrent.Search.searchSeedsFilter.min : 0;
+ let maxSeeds = (window.qBittorrent.Search.searchSeedsFilter.max > 0) ? window.qBittorrent.Search.searchSeedsFilter.max : 0;
- this.columns['files'].updateTd = function(td, row) {
- td.innerHTML = escapeHtml(this.getRowValue(row, 0).replace(/\n/g, ';'));
- td.title = escapeHtml(this.getRowValue(row, 0));
- };
+ if ((minSeeds > maxSeeds) && (maxSeeds > 0)) {
+ const tmp = minSeeds;
+ minSeeds = maxSeeds;
+ maxSeeds = tmp;
+ }
- }
-});
+ return {
+ min: minSeeds,
+ max: maxSeeds
+ }
+ };
-const SearchResultsTable = new Class({
- Extends: DynamicTable,
+ let filteredRows = [];
+ const rows = this.rows.getValues();
+ const searchTerms = window.qBittorrent.Search.searchText.pattern.toLowerCase().split(" ");
+ const filterTerms = window.qBittorrent.Search.searchText.filterPattern.toLowerCase().split(" ");
+ const sizeFilters = getSizeFilters();
+ const seedsFilters = getSeedsFilters();
+ const searchInTorrentName = $('searchInTorrentName').get('value') === "names";
+
+ if (searchInTorrentName || (filterTerms.length > 0) || (window.qBittorrent.Search.searchSizeFilter.min > 0.00) || (window.qBittorrent.Search.searchSizeFilter.max > 0.00)) {
+ for (let i = 0; i < rows.length; ++i) {
+ const row = rows[i];
+
+ if (searchInTorrentName && !window.qBittorrent.Misc.containsAllTerms(row.full_data.fileName, searchTerms)) continue;
+ if ((filterTerms.length > 0) && !window.qBittorrent.Misc.containsAllTerms(row.full_data.fileName, filterTerms)) continue;
+ if ((sizeFilters.min > 0.00) && (row.full_data.fileSize < sizeFilters.min)) continue;
+ if ((sizeFilters.max > 0.00) && (row.full_data.fileSize > sizeFilters.max)) continue;
+ if ((seedsFilters.min > 0) && (row.full_data.nbSeeders < seedsFilters.min)) continue;
+ if ((seedsFilters.max > 0) && (row.full_data.nbSeeders > seedsFilters.max)) continue;
+
+ filteredRows.push(row);
+ }
+ }
+ else {
+ filteredRows = rows;
+ }
- initColumns: function() {
- this.newColumn('fileName', '', 'QBT_TR(Name)QBT_TR[CONTEXT=SearchResultsTable]', 500, true);
- this.newColumn('fileSize', '', 'QBT_TR(Size)QBT_TR[CONTEXT=SearchResultsTable]', 100, true);
- this.newColumn('nbSeeders', '', 'QBT_TR(Seeders)QBT_TR[CONTEXT=SearchResultsTable]', 100, true);
- this.newColumn('nbLeechers', '', 'QBT_TR(Leechers)QBT_TR[CONTEXT=SearchResultsTable]', 100, true);
- this.newColumn('siteUrl', '', 'QBT_TR(Search engine)QBT_TR[CONTEXT=SearchResultsTable]', 250, true);
+ filteredRows.sort(function(row1, row2) {
+ const column = this.columns[this.sortedColumn];
+ const res = column.compareRows(row1, row2);
+ if (this.reverseSort === '0')
+ return res;
+ else
+ return -res;
+ }.bind(this));
- this.initColumnsFunctions();
- },
+ return filteredRows;
+ },
- initColumnsFunctions: function() {
- const displayText = function(td, row) {
- const value = escapeHtml(this.getRowValue(row));
- td.set('html', value);
- td.set('title', value);
+ setupTr: function(tr) {
+ tr.addClass("searchTableRow");
}
- const displaySize = function(td, row) {
- const size = friendlyUnit(this.getRowValue(row), false);
- td.set('html', size);
- td.set('title', size);
- }
- const displayNum = function(td, row) {
- const value = escapeHtml(this.getRowValue(row));
- const formattedValue = (value === "-1") ? "Unknown" : value;
- td.set('html', formattedValue);
- td.set('title', formattedValue);
- }
-
- this.columns['fileName'].updateTd = displayText;
- this.columns['fileSize'].updateTd = displaySize;
- this.columns['nbSeeders'].updateTd = displayNum;
- this.columns['nbLeechers'].updateTd = displayNum;
- this.columns['siteUrl'].updateTd = displayText;
- },
-
- getFilteredAndSortedRows: function() {
- const getSizeFilters = function() {
- let minSize = (searchSizeFilter.min > 0.00) ? (searchSizeFilter.min * Math.pow(1024, searchSizeFilter.minUnit)) : 0.00;
- let maxSize = (searchSizeFilter.max > 0.00) ? (searchSizeFilter.max * Math.pow(1024, searchSizeFilter.maxUnit)) : 0.00;
-
- if ((minSize > maxSize) && (maxSize > 0.00)) {
- const tmp = minSize;
- minSize = maxSize;
- maxSize = tmp;
- }
+ });
- return {
- min: minSize,
- max: maxSize
- }
- };
+ const SearchPluginsTable = new Class({
+ Extends: DynamicTable,
- const getSeedsFilters = function() {
- let minSeeds = (searchSeedsFilter.min > 0) ? searchSeedsFilter.min : 0;
- let maxSeeds = (searchSeedsFilter.max > 0) ? searchSeedsFilter.max : 0;
+ initColumns: function() {
+ this.newColumn('fullName', '', 'QBT_TR(Name)QBT_TR[CONTEXT=SearchPluginsTable]', 175, true);
+ this.newColumn('version', '', 'QBT_TR(Version)QBT_TR[CONTEXT=SearchPluginsTable]', 100, true);
+ this.newColumn('url', '', 'QBT_TR(Url)QBT_TR[CONTEXT=SearchPluginsTable]', 175, true);
+ this.newColumn('enabled', '', 'QBT_TR(Enabled)QBT_TR[CONTEXT=SearchPluginsTable]', 100, true);
- if ((minSeeds > maxSeeds) && (maxSeeds > 0)) {
- const tmp = minSeeds;
- minSeeds = maxSeeds;
- maxSeeds = tmp;
- }
+ this.initColumnsFunctions();
+ },
- return {
- min: minSeeds,
- max: maxSeeds
+ initColumnsFunctions: function() {
+ const displayText = function(td, row) {
+ const value = window.qBittorrent.Misc.escapeHtml(this.getRowValue(row));
+ td.set('html', value);
+ td.set('title', value);
}
- };
- let filteredRows = [];
- const rows = this.rows.getValues();
- const searchTerms = searchPattern.toLowerCase().split(" ");
- const filterTerms = searchFilterPattern.toLowerCase().split(" ");
- const sizeFilters = getSizeFilters();
- const seedsFilters = getSeedsFilters();
- const searchInTorrentName = $('searchInTorrentName').get('value') === "names";
-
- if (searchInTorrentName || (filterTerms.length > 0) || (searchSizeFilter.min > 0.00) || (searchSizeFilter.max > 0.00)) {
- for (let i = 0; i < rows.length; ++i) {
- const row = rows[i];
-
- if (searchInTorrentName && !containsAllTerms(row.full_data.fileName, searchTerms)) continue;
- if ((filterTerms.length > 0) && !containsAllTerms(row.full_data.fileName, filterTerms)) continue;
- if ((sizeFilters.min > 0.00) && (row.full_data.fileSize < sizeFilters.min)) continue;
- if ((sizeFilters.max > 0.00) && (row.full_data.fileSize > sizeFilters.max)) continue;
- if ((seedsFilters.min > 0) && (row.full_data.nbSeeders < seedsFilters.min)) continue;
- if ((seedsFilters.max > 0) && (row.full_data.nbSeeders > seedsFilters.max)) continue;
+ this.columns['fullName'].updateTd = displayText;
+ this.columns['version'].updateTd = displayText;
+ this.columns['url'].updateTd = displayText;
+ this.columns['enabled'].updateTd = function(td, row) {
+ const value = this.getRowValue(row);
+ if (value) {
+ td.set('html', "Yes");
+ td.set('title', "Yes");
+ td.getParent("tr").addClass("green");
+ td.getParent("tr").removeClass("red");
+ }
+ else {
+ td.set('html', "No");
+ td.set('title', "No");
+ td.getParent("tr").addClass("red");
+ td.getParent("tr").removeClass("green");
+ }
+ };
+ },
- filteredRows.push(row);
- }
- }
- else {
- filteredRows = rows;
+ setupTr: function(tr) {
+ tr.addClass("searchPluginsTableRow");
}
+ });
+
+ const TorrentTrackersTable = new Class({
+ Extends: DynamicTable,
+
+ initColumns: function() {
+ this.newColumn('tier', '', 'QBT_TR(Tier)QBT_TR[CONTEXT=TrackerListWidget]', 35, true);
+ this.newColumn('url', '', 'QBT_TR(URL)QBT_TR[CONTEXT=TrackerListWidget]', 250, true);
+ this.newColumn('status', '', 'QBT_TR(Status)QBT_TR[CONTEXT=TrackerListWidget]', 125, true);
+ this.newColumn('peers', '', 'QBT_TR(Peers)QBT_TR[CONTEXT=TrackerListWidget]', 75, true);
+ this.newColumn('seeds', '', 'QBT_TR(Seeds)QBT_TR[CONTEXT=TrackerListWidget]', 75, true);
+ this.newColumn('leeches', '', 'QBT_TR(Leeches)QBT_TR[CONTEXT=TrackerListWidget]', 75, true);
+ this.newColumn('downloaded', '', 'QBT_TR(Downloaded)QBT_TR[CONTEXT=TrackerListWidget]', 100, true);
+ this.newColumn('message', '', 'QBT_TR(Message)QBT_TR[CONTEXT=TrackerListWidget]', 250, true);
+ },
+ });
+
+ const TorrentFilesTable = new Class({
+ Extends: DynamicTable,
+
+ filterTerms: [],
+ prevFilterTerms: [],
+ prevRowsString: null,
+ prevFilteredRows: [],
+ prevSortedColumn: null,
+ prevReverseSort: null,
+ fileTree: new window.qBittorrent.FileTree.FileTree(),
+
+ populateTable: function(root) {
+ this.fileTree.setRoot(root);
+ root.children.each(function(node) {
+ this._addNodeToTable(node, 0);
+ }.bind(this));
+ },
- filteredRows.sort(function(row1, row2) {
- const column = this.columns[this.sortedColumn];
- const res = column.compareRows(row1, row2);
- if (this.reverseSort === '0')
- return res;
- else
- return -res;
- }.bind(this));
-
- return filteredRows;
- },
-
- setupTr: function(tr) {
- tr.addClass("searchTableRow");
- }
-});
-
-const SearchPluginsTable = new Class({
- Extends: DynamicTable,
-
- initColumns: function() {
- this.newColumn('fullName', '', 'QBT_TR(Name)QBT_TR[CONTEXT=SearchPluginsTable]', 175, true);
- this.newColumn('version', '', 'QBT_TR(Version)QBT_TR[CONTEXT=SearchPluginsTable]', 100, true);
- this.newColumn('url', '', 'QBT_TR(Url)QBT_TR[CONTEXT=SearchPluginsTable]', 175, true);
- this.newColumn('enabled', '', 'QBT_TR(Enabled)QBT_TR[CONTEXT=SearchPluginsTable]', 100, true);
-
- this.initColumnsFunctions();
- },
-
- initColumnsFunctions: function() {
- const displayText = function(td, row) {
- const value = escapeHtml(this.getRowValue(row));
- td.set('html', value);
- td.set('title', value);
- }
+ _addNodeToTable: function(node, depth) {
+ node.depth = depth;
- this.columns['fullName'].updateTd = displayText;
- this.columns['version'].updateTd = displayText;
- this.columns['url'].updateTd = displayText;
- this.columns['enabled'].updateTd = function(td, row) {
- const value = this.getRowValue(row);
- if (value) {
- td.set('html', "Yes");
- td.set('title', "Yes");
- td.getParent("tr").addClass("green");
- td.getParent("tr").removeClass("red");
+ if (node.isFolder) {
+ const data = {
+ rowId: node.rowId,
+ size: node.size,
+ checked: node.checked,
+ remaining: node.remaining,
+ progress: node.progress,
+ priority: window.qBittorrent.PropFiles.normalizePriority(node.priority),
+ availability: node.availability,
+ fileId: -1,
+ name: node.name
+ };
+
+ node.data = data;
+ node.full_data = data;
+ this.updateRowData(data);
}
else {
- td.set('html', "No");
- td.set('title', "No");
- td.getParent("tr").addClass("red");
- td.getParent("tr").removeClass("green");
+ node.data.rowId = node.rowId;
+ node.full_data = node.data;
+ this.updateRowData(node.data);
}
- };
- },
-
- setupTr: function(tr) {
- tr.addClass("searchPluginsTableRow");
- }
-});
-
-const TorrentTrackersTable = new Class({
- Extends: DynamicTable,
-
- initColumns: function() {
- this.newColumn('tier', '', 'QBT_TR(Tier)QBT_TR[CONTEXT=TrackerListWidget]', 35, true);
- this.newColumn('url', '', 'QBT_TR(URL)QBT_TR[CONTEXT=TrackerListWidget]', 250, true);
- this.newColumn('status', '', 'QBT_TR(Status)QBT_TR[CONTEXT=TrackerListWidget]', 125, true);
- this.newColumn('peers', '', 'QBT_TR(Peers)QBT_TR[CONTEXT=TrackerListWidget]', 75, true);
- this.newColumn('seeds', '', 'QBT_TR(Seeds)QBT_TR[CONTEXT=TrackerListWidget]', 75, true);
- this.newColumn('leeches', '', 'QBT_TR(Leeches)QBT_TR[CONTEXT=TrackerListWidget]', 75, true);
- this.newColumn('downloaded', '', 'QBT_TR(Downloaded)QBT_TR[CONTEXT=TrackerListWidget]', 100, true);
- this.newColumn('message', '', 'QBT_TR(Message)QBT_TR[CONTEXT=TrackerListWidget]', 250, true);
- },
-});
-
-const TorrentFilesTable = new Class({
- Extends: DynamicTable,
-
- filterTerms: [],
- prevFilterTerms: [],
- prevRowsString: null,
- prevFilteredRows: [],
- prevSortedColumn: null,
- prevReverseSort: null,
- fileTree: new FileTree(),
-
- populateTable: function(root) {
- this.fileTree.setRoot(root);
- root.children.each(function(node) {
- this._addNodeToTable(node, 0);
- }.bind(this));
- },
-
- _addNodeToTable: function(node, depth) {
- node.depth = depth;
-
- if (node.isFolder) {
- const data = {
- rowId: node.rowId,
- size: node.size,
- checked: node.checked,
- remaining: node.remaining,
- progress: node.progress,
- priority: normalizePriority(node.priority),
- availability: node.availability,
- fileId: -1,
- name: node.name
- };
-
- node.data = data;
- node.full_data = data;
- this.updateRowData(data);
- }
- else {
- node.data.rowId = node.rowId;
- node.full_data = node.data;
- this.updateRowData(node.data);
- }
-
- node.children.each(function(child) {
- this._addNodeToTable(child, depth + 1);
- }.bind(this));
- },
-
- getRoot: function() {
- return this.fileTree.getRoot();
- },
-
- getNode: function(rowId) {
- return this.fileTree.getNode(rowId);
- },
-
- getRow: function(node) {
- const rowId = this.fileTree.getRowId(node);
- return this.rows.get(rowId);
- },
-
- initColumns: function() {
- this.newColumn('checked', '', '', 50, true);
- this.newColumn('name', '', 'QBT_TR(Name)QBT_TR[CONTEXT=TrackerListWidget]', 300, true);
- this.newColumn('size', '', 'QBT_TR(Size)QBT_TR[CONTEXT=TrackerListWidget]', 75, true);
- this.newColumn('progress', '', 'QBT_TR(Progress)QBT_TR[CONTEXT=TrackerListWidget]', 100, true);
- this.newColumn('priority', '', 'QBT_TR(Download Priority)QBT_TR[CONTEXT=TrackerListWidget]', 150, true);
- this.newColumn('remaining', '', 'QBT_TR(Remaining)QBT_TR[CONTEXT=TrackerListWidget]', 75, true);
- this.newColumn('availability', '', 'QBT_TR(Availability)QBT_TR[CONTEXT=TrackerListWidget]', 75, true);
-
- this.initColumnsFunctions();
- },
-
- initColumnsFunctions: function() {
- const that = this;
- const displaySize = function(td, row) {
- const size = friendlyUnit(this.getRowValue(row), false);
- td.set('html', size);
- td.set('title', size);
- }
- const displayPercentage = function(td, row) {
- const value = friendlyPercentage(this.getRowValue(row));
- td.set('html', value);
- td.set('title', value);
- };
- this.columns['name'].updateTd = function(td, row) {
- const id = row.rowId;
- const fileNameId = 'filesTablefileName' + id;
- const node = that.getNode(id);
+ node.children.each(function(child) {
+ this._addNodeToTable(child, depth + 1);
+ }.bind(this));
+ },
+
+ getRoot: function() {
+ return this.fileTree.getRoot();
+ },
+
+ getNode: function(rowId) {
+ return this.fileTree.getNode(rowId);
+ },
+
+ getRow: function(node) {
+ const rowId = this.fileTree.getRowId(node);
+ return this.rows.get(rowId);
+ },
+
+ initColumns: function() {
+ this.newColumn('checked', '', '', 50, true);
+ this.newColumn('name', '', 'QBT_TR(Name)QBT_TR[CONTEXT=TrackerListWidget]', 300, true);
+ this.newColumn('size', '', 'QBT_TR(Size)QBT_TR[CONTEXT=TrackerListWidget]', 75, true);
+ this.newColumn('progress', '', 'QBT_TR(Progress)QBT_TR[CONTEXT=TrackerListWidget]', 100, true);
+ this.newColumn('priority', '', 'QBT_TR(Download Priority)QBT_TR[CONTEXT=TrackerListWidget]', 150, true);
+ this.newColumn('remaining', '', 'QBT_TR(Remaining)QBT_TR[CONTEXT=TrackerListWidget]', 75, true);
+ this.newColumn('availability', '', 'QBT_TR(Availability)QBT_TR[CONTEXT=TrackerListWidget]', 75, true);
+
+ this.initColumnsFunctions();
+ },
+
+ initColumnsFunctions: function() {
+ const that = this;
+ const displaySize = function(td, row) {
+ const size = window.qBittorrent.Misc.friendlyUnit(this.getRowValue(row), false);
+ td.set('html', size);
+ td.set('title', size);
+ }
+ const displayPercentage = function(td, row) {
+ const value = window.qBittorrent.Misc.friendlyPercentage(this.getRowValue(row));
+ td.set('html', value);
+ td.set('title', value);
+ };
- if (node.isFolder) {
- const value = this.getRowValue(row);
- const collapseIconId = 'filesTableCollapseIcon' + id;
- const dirImgId = 'filesTableDirImg' + id;
- if ($(dirImgId)) {
- // just update file name
- $(fileNameId).textContent = escapeHtml(value);
+ this.columns['name'].updateTd = function(td, row) {
+ const id = row.rowId;
+ const fileNameId = 'filesTablefileName' + id;
+ const node = that.getNode(id);
+
+ if (node.isFolder) {
+ const value = this.getRowValue(row);
+ const collapseIconId = 'filesTableCollapseIcon' + id;
+ const dirImgId = 'filesTableDirImg' + id;
+ if ($(dirImgId)) {
+ // just update file name
+ $(fileNameId).textContent = window.qBittorrent.Misc.escapeHtml(value);
+ }
+ else {
+ const collapseIcon = new Element('img', {
+ src: 'images/qbt-theme/go-down.svg',
+ styles: {
+ 'margin-left': (node.depth * 20)
+ },
+ class: "filesTableCollapseIcon",
+ id: collapseIconId,
+ "data-id": id,
+ onclick: "qBittorrent.PropFiles.collapseIconClicked(this)"
+ });
+ const span = new Element('span', {
+ text: window.qBittorrent.Misc.escapeHtml(value),
+ id: fileNameId
+ });
+ const dirImg = new Element('img', {
+ src: 'images/qbt-theme/inode-directory.svg',
+ styles: {
+ 'width': 15,
+ 'padding-right': 5,
+ 'margin-bottom': -3
+ },
+ id: dirImgId
+ });
+ const html = collapseIcon.outerHTML + dirImg.outerHTML + span.outerHTML;
+ td.set('html', html);
+ }
}
else {
- const collapseIcon = new Element('img', {
- src: 'images/qbt-theme/go-down.svg',
- styles: {
- 'margin-left': (node.depth * 20)
- },
- class: "filesTableCollapseIcon",
- id: collapseIconId,
- "data-id": id,
- onclick: "collapseIconClicked(this)"
- });
+ const value = this.getRowValue(row);
const span = new Element('span', {
- text: escapeHtml(value),
- id: fileNameId
- });
- const dirImg = new Element('img', {
- src: 'images/qbt-theme/inode-directory.svg',
+ text: window.qBittorrent.Misc.escapeHtml(value),
+ id: fileNameId,
styles: {
- 'width': 15,
- 'padding-right': 5,
- 'margin-bottom': -3
- },
- id: dirImgId
+ 'margin-left': ((node.depth + 1) * 20)
+ }
});
- const html = collapseIcon.outerHTML + dirImg.outerHTML + span.outerHTML;
- td.set('html', html);
+ td.set('html', span.outerHTML);
}
- }
- else {
- const value = this.getRowValue(row);
- const span = new Element('span', {
- text: escapeHtml(value),
- id: fileNameId,
- styles: {
- 'margin-left': ((node.depth + 1) * 20)
- }
- });
- td.set('html', span.outerHTML);
- }
- };
+ };
- this.columns['checked'].updateTd = function(td, row) {
- const id = row.rowId;
- const value = this.getRowValue(row);
+ this.columns['checked'].updateTd = function(td, row) {
+ const id = row.rowId;
+ const value = this.getRowValue(row);
- if (isDownloadCheckboxExists(id)) {
- updateDownloadCheckbox(id, value);
- }
- else {
- const treeImg = new Element('img', {
- src: 'images/L.gif',
- styles: {
- 'margin-bottom': -2
- }
- });
- td.adopt(treeImg, createDownloadCheckbox(id, row.full_data.fileId, value));
- }
- };
+ if (window.qBittorrent.PropFiles.isDownloadCheckboxExists(id)) {
+ window.qBittorrent.PropFiles.updateDownloadCheckbox(id, value);
+ }
+ else {
+ const treeImg = new Element('img', {
+ src: 'images/L.gif',
+ styles: {
+ 'margin-bottom': -2
+ }
+ });
+ td.adopt(treeImg, window.qBittorrent.PropFiles.createDownloadCheckbox(id, row.full_data.fileId, value));
+ }
+ };
- this.columns['size'].updateTd = displaySize;
+ this.columns['size'].updateTd = displaySize;
- this.columns['progress'].updateTd = function(td, row) {
- const id = row.rowId;
- const value = this.getRowValue(row);
+ this.columns['progress'].updateTd = function(td, row) {
+ const id = row.rowId;
+ const value = this.getRowValue(row);
- const progressBar = $('pbf_' + id);
- if (progressBar === null) {
- td.adopt(new ProgressBar(value.toFloat(), {
- id: 'pbf_' + id,
- width: 80
- }));
- }
- else {
- progressBar.setValue(value.toFloat());
- }
- };
+ const progressBar = $('pbf_' + id);
+ if (progressBar === null) {
+ td.adopt(new window.qBittorrent.ProgressBar.ProgressBar(value.toFloat(), {
+ id: 'pbf_' + id,
+ width: 80
+ }));
+ }
+ else {
+ progressBar.setValue(value.toFloat());
+ }
+ };
- this.columns['priority'].updateTd = function(td, row) {
- const id = row.rowId;
- const value = this.getRowValue(row);
+ this.columns['priority'].updateTd = function(td, row) {
+ const id = row.rowId;
+ const value = this.getRowValue(row);
- if (isPriorityComboExists(id))
- updatePriorityCombo(id, value);
- else
- td.adopt(createPriorityCombo(id, row.full_data.fileId, value));
- };
+ if (window.qBittorrent.PropFiles.isPriorityComboExists(id))
+ window.qBittorrent.PropFiles.updatePriorityCombo(id, value);
+ else
+ td.adopt(window.qBittorrent.PropFiles.createPriorityCombo(id, row.full_data.fileId, value));
+ };
- this.columns['remaining'].updateTd = displaySize;
- this.columns['availability'].updateTd = displayPercentage;
- },
+ this.columns['remaining'].updateTd = displaySize;
+ this.columns['availability'].updateTd = displayPercentage;
+ },
- altRow: function() {
- let addClass = false;
- const trs = this.tableBody.getElements('tr');
- trs.each(function(tr) {
- if (tr.hasClass("invisible"))
- return;
+ altRow: function() {
+ let addClass = false;
+ const trs = this.tableBody.getElements('tr');
+ trs.each(function(tr) {
+ if (tr.hasClass("invisible"))
+ return;
- if (addClass){
- tr.addClass("alt");
- tr.removeClass("nonAlt");
- }
- else {
- tr.removeClass("alt");
- tr.addClass("nonAlt");
- }
- addClass = !addClass;
- }.bind(this));
- },
-
- _sortNodesByColumn: function(nodes, column) {
- nodes.sort(function(row1, row2) {
- // list folders before files when sorting by name
- if (column.name === "name") {
- const node1 = this.getNode(row1.data.rowId);
- const node2 = this.getNode(row2.data.rowId);
- if (node1.isFolder && !node2.isFolder)
- return -1;
- if (node2.isFolder && !node1.isFolder)
- return 1;
- }
+ if (addClass){
+ tr.addClass("alt");
+ tr.removeClass("nonAlt");
+ }
+ else {
+ tr.removeClass("alt");
+ tr.addClass("nonAlt");
+ }
+ addClass = !addClass;
+ }.bind(this));
+ },
+
+ _sortNodesByColumn: function(nodes, column) {
+ nodes.sort(function(row1, row2) {
+ // list folders before files when sorting by name
+ if (column.name === "name") {
+ const node1 = this.getNode(row1.data.rowId);
+ const node2 = this.getNode(row2.data.rowId);
+ if (node1.isFolder && !node2.isFolder)
+ return -1;
+ if (node2.isFolder && !node1.isFolder)
+ return 1;
+ }
- const res = column.compareRows(row1, row2);
- return (this.reverseSort === '0') ? res : -res;
- }.bind(this));
+ const res = column.compareRows(row1, row2);
+ return (this.reverseSort === '0') ? res : -res;
+ }.bind(this));
- nodes.each(function(node) {
- if (node.children.length > 0)
- this._sortNodesByColumn(node.children, column);
- }.bind(this));
- },
+ nodes.each(function(node) {
+ if (node.children.length > 0)
+ this._sortNodesByColumn(node.children, column);
+ }.bind(this));
+ },
- _filterNodes: function(node, filterTerms, filteredRows) {
- if (node.isFolder) {
- const childAdded = node.children.reduce(function (acc, child) {
- // we must execute the function before ORing w/ acc or we'll stop checking child nodes after the first successful match
- return (this._filterNodes(child, filterTerms, filteredRows) || acc);
- }.bind(this), false);
+ _filterNodes: function(node, filterTerms, filteredRows) {
+ if (node.isFolder) {
+ const childAdded = node.children.reduce(function (acc, child) {
+ // we must execute the function before ORing w/ acc or we'll stop checking child nodes after the first successful match
+ return (this._filterNodes(child, filterTerms, filteredRows) || acc);
+ }.bind(this), false);
+
+ if (childAdded) {
+ const row = this.getRow(node);
+ filteredRows.push(row);
+ return true;
+ }
+ }
- if (childAdded) {
+ if (window.qBittorrent.Misc.containsAllTerms(node.name, filterTerms)) {
const row = this.getRow(node);
filteredRows.push(row);
return true;
}
- }
- if (containsAllTerms(node.name, filterTerms)) {
- const row = this.getRow(node);
- filteredRows.push(row);
- return true;
- }
+ return false;
+ },
- return false;
- },
+ setFilter: function(text) {
+ const filterTerms = text.trim().toLowerCase().split(' ');
+ if ((filterTerms.length === 1) && (filterTerms[0] === ''))
+ this.filterTerms = [];
+ else
+ this.filterTerms = filterTerms;
+ },
- setFilter: function(text) {
- const filterTerms = text.trim().toLowerCase().split(' ');
- if ((filterTerms.length === 1) && (filterTerms[0] === ''))
- this.filterTerms = [];
- else
- this.filterTerms = filterTerms;
- },
+ getFilteredAndSortedRows: function() {
+ if (this.getRoot() === null)
+ return [];
- getFilteredAndSortedRows: function() {
- if (this.getRoot() === null)
- return [];
+ const generateRowsSignature = function(rows) {
+ const rowsData = rows.map(function(row) {
+ return row.full_data;
+ });
+ return JSON.stringify(rowsData);
+ };
- const generateRowsSignature = function(rows) {
- const rowsData = rows.map(function(row) {
- return row.full_data;
- });
- return JSON.stringify(rowsData);
- };
+ const getFilteredRows = function() {
+ if (this.filterTerms.length === 0) {
+ const nodeArray = this.fileTree.toArray();
+ const filteredRows = nodeArray.map(function(node) {
+ return this.getRow(node);
+ }.bind(this));
+ return filteredRows;
+ }
- const getFilteredRows = function() {
- if (this.filterTerms.length === 0) {
- const nodeArray = this.fileTree.toArray();
- const filteredRows = nodeArray.map(function(node) {
- return this.getRow(node);
+ const filteredRows = [];
+ this.getRoot().children.each(function(child) {
+ this._filterNodes(child, this.filterTerms, filteredRows);
}.bind(this));
+ filteredRows.reverse();
return filteredRows;
+ }.bind(this);
+
+ const hasRowsChanged = function(rowsString, prevRowsStringString) {
+ const rowsChanged = (rowsString !== prevRowsStringString);
+ const isFilterTermsChanged = this.filterTerms.reduce(function(acc, term, index) {
+ return (acc || (term !== this.prevFilterTerms[index]));
+ }.bind(this), false);
+ const isFilterChanged = ((this.filterTerms.length !== this.prevFilterTerms.length)
+ || ((this.filterTerms.length > 0) && isFilterTermsChanged));
+ const isSortedColumnChanged = (this.prevSortedColumn !== this.sortedColumn);
+ const isReverseSortChanged = (this.prevReverseSort !== this.reverseSort);
+
+ return (rowsChanged || isFilterChanged || isSortedColumnChanged || isReverseSortChanged);
+ }.bind(this);
+
+ const rowsString = generateRowsSignature(this.rows);
+ if (!hasRowsChanged(rowsString, this.prevRowsString)) {
+ return this.prevFilteredRows;
}
- const filteredRows = [];
- this.getRoot().children.each(function(child) {
- this._filterNodes(child, this.filterTerms, filteredRows);
- }.bind(this));
- filteredRows.reverse();
+ // sort, then filter
+ const column = this.columns[this.sortedColumn];
+ this._sortNodesByColumn(this.getRoot().children, column);
+ const filteredRows = getFilteredRows();
+
+ this.prevFilterTerms = this.filterTerms;
+ this.prevRowsString = rowsString;
+ this.prevFilteredRows = filteredRows;
+ this.prevSortedColumn = this.sortedColumn;
+ this.prevReverseSort = this.reverseSort;
return filteredRows;
- }.bind(this);
-
- const hasRowsChanged = function(rowsString, prevRowsStringString) {
- const rowsChanged = (rowsString !== prevRowsStringString);
- const isFilterTermsChanged = this.filterTerms.reduce(function(acc, term, index) {
- return (acc || (term !== this.prevFilterTerms[index]));
- }.bind(this), false);
- const isFilterChanged = ((this.filterTerms.length !== this.prevFilterTerms.length)
- || ((this.filterTerms.length > 0) && isFilterTermsChanged));
- const isSortedColumnChanged = (this.prevSortedColumn !== this.sortedColumn);
- const isReverseSortChanged = (this.prevReverseSort !== this.reverseSort);
-
- return (rowsChanged || isFilterChanged || isSortedColumnChanged || isReverseSortChanged);
- }.bind(this);
-
- const rowsString = generateRowsSignature(this.rows);
- if (!hasRowsChanged(rowsString, this.prevRowsString)) {
- return this.prevFilteredRows;
+ },
+
+ setIgnored: function(rowId, ignore) {
+ const row = this.rows.get(rowId);
+ if (ignore)
+ row.full_data.remaining = 0;
+ else
+ row.full_data.remaining = (row.full_data.size * (1.0 - (row.full_data.progress / 100)));
}
+ });
- // sort, then filter
- const column = this.columns[this.sortedColumn];
- this._sortNodesByColumn(this.getRoot().children, column);
- const filteredRows = getFilteredRows();
-
- this.prevFilterTerms = this.filterTerms;
- this.prevRowsString = rowsString;
- this.prevFilteredRows = filteredRows;
- this.prevSortedColumn = this.sortedColumn;
- this.prevReverseSort = this.reverseSort;
- return filteredRows;
- },
-
- setIgnored: function(rowId, ignore) {
- const row = this.rows.get(rowId);
- if (ignore)
- row.full_data.remaining = 0;
- else
- row.full_data.remaining = (row.full_data.size * (1.0 - (row.full_data.progress / 100)));
- }
-});
+ return exports();
+})();
/*************************************************************/
diff --git a/src/webui/www/private/scripts/file-tree.js b/src/webui/www/private/scripts/file-tree.js
index c84738f29..9fbeebc01 100644
--- a/src/webui/www/private/scripts/file-tree.js
+++ b/src/webui/www/private/scripts/file-tree.js
@@ -28,149 +28,167 @@
'use strict';
-const FilePriority = {
- "Ignored": 0,
- "Normal": 1,
- "High": 6,
- "Maximum": 7,
- "Mixed": -1
-};
-Object.freeze(FilePriority);
-
-const TriState = {
- "Unchecked": 0,
- "Checked": 1,
- "Partial": 2
-};
-Object.freeze(TriState);
-
-const FileTree = new Class({
- root: null,
- nodeMap: {},
-
- setRoot: function(root) {
- this.root = root;
- this.generateNodeMap(root);
-
- 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));
- }
-});
-
-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: [],
-});
-
-const FolderNode = new Class({
- Extends: FileNode,
-
- initialize: function() {
- this.isFolder = true;
- },
-
- addChild(node) {
- this.children.push(node);
- },
-
- /**
- * 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;
-
- let isFirstFile = true;
-
- 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;
+if (window.qBittorrent === undefined) {
+ window.qBittorrent = {};
+}
+
+window.qBittorrent.FileTree = (function() {
+ const exports = function() {
+ return {
+ FilePriority: FilePriority,
+ TriState: TriState,
+ FileTree: FileTree,
+ FileNode: FileNode,
+ FolderNode: FolderNode,
+ };
+ };
+
+ const FilePriority = {
+ "Ignored": 0,
+ "Normal": 1,
+ "High": 6,
+ "Maximum": 7,
+ "Mixed": -1
+ };
+ Object.freeze(FilePriority);
+
+ const TriState = {
+ "Unchecked": 0,
+ "Checked": 1,
+ "Partial": 2
+ };
+ Object.freeze(TriState);
+
+ const FileTree = new Class({
+ root: null,
+ nodeMap: {},
+
+ setRoot: function(root) {
+ this.root = root;
+ this.generateNodeMap(root);
+
+ 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;
}
- 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);
- }
-});
+ 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));
+ }
+ });
+
+ 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: [],
+ });
+
+ const FolderNode = new Class({
+ Extends: FileNode,
+
+ initialize: function() {
+ this.isFolder = true;
+ },
+
+ addChild(node) {
+ this.children.push(node);
+ },
+
+ /**
+ * 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;
+
+ let isFirstFile = true;
+
+ 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();
+})();
diff --git a/src/webui/www/private/scripts/filesystem.js b/src/webui/www/private/scripts/filesystem.js
index 5a9df7d8e..0cd87241f 100644
--- a/src/webui/www/private/scripts/filesystem.js
+++ b/src/webui/www/private/scripts/filesystem.js
@@ -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();
+})();
diff --git a/src/webui/www/private/scripts/misc.js b/src/webui/www/private/scripts/misc.js
index 32f4dc24d..1671f1525 100644
--- a/src/webui/www/private/scripts/misc.js
+++ b/src/webui/www/private/scripts/misc.js
@@ -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;
- }
+if (window.qBittorrent === undefined) {
+ window.qBittorrent = {};
+}
- function friendlyUnitPrecision(sizeUnit) {
- if (sizeUnit <= 2) return 1; // KiB, MiB
- else if (sizeUnit === 3) return 2; // GiB
- else return 3; // TiB, PiB, EiB
- }
+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]"
+ ];
+
+ 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;
+ }
- 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];
- }
+ function friendlyUnitPrecision(sizeUnit) {
+ if (sizeUnit <= 2) return 1; // KiB, MiB
+ else if (sizeUnit === 3) return 2; // GiB
+ else return 3; // TiB, PiB, EiB
+ }
- if (isSpeed)
- ret += "QBT_TR(/s)QBT_TR[CONTEXT=misc]";
- return ret;
-}
+ 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];
+ }
-/*
- * 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 "∞";
-}
+ if (isSpeed)
+ ret += "QBT_TR(/s)QBT_TR[CONTEXT=misc]";
+ return ret;
+ }
-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) + "%";
-}
+ /*
+ * 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 "∞";
+ }
-function friendlyFloat(value, precision) {
- return parseFloat(value).toFixed(precision);
-}
+ 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) + "%";
+ }
-/*
- * From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString
- */
-if (!Date.prototype.toISOString) {
- (function() {
+ const friendlyFloat = function(value, precision) {
+ return parseFloat(value).toFixed(precision);
+ }
- function pad(number) {
- if (number < 10) {
- return '0' + number;
+ /*
+ * 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;
}
- 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';
- };
- }());
-}
+ 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
- */
-function parseHtmlLinks(text) {
- const exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
- return text.replace(exp, "$1");
-}
+ /*
+ * 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, "$1");
+ }
-function escapeHtml(str) {
- const div = document.createElement('div');
- div.appendChild(document.createTextNode(str));
- return div.innerHTML;
-}
+ const escapeHtml = function(str) {
+ const div = document.createElement('div');
+ div.appendChild(document.createTextNode(str));
+ return div.innerHTML;
+ }
-function safeTrim(value) {
- try {
- return value.trim();
+ const safeTrim = function(value) {
+ try {
+ return value.trim();
+ }
+ catch (e) {
+ if (e instanceof TypeError)
+ return "";
+ throw e;
+ }
}
- 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);
}
-}
-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} 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);
+ }
-/**
- *
- * @param {String} text the text to search
- * @param {Array} 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);
- }
+ const textContainsTerm = (textToSearch.indexOf(term) !== -1);
+ return isTermExcluded ? !textContainsTerm : textContainsTerm;
+ }));
+ }
- const textContainsTerm = (textToSearch.indexOf(term) !== -1);
- return isTermExcluded ? !textContainsTerm : textContainsTerm;
- }));
-}
+ return exports();
+})();
diff --git a/src/webui/www/private/scripts/mocha-init.js b/src/webui/www/private/scripts/mocha-init.js
index 9bae8c74f..7941b2168 100644
--- a/src/webui/www/private/scripts/mocha-init.js
+++ b/src/webui/www/private/scripts/mocha-init.js
@@ -38,7 +38,7 @@
----------------------------------------------------------------- */
'use strict';
-const LocalPreferences = new LocalPreferencesClass();
+const LocalPreferences = new window.qBittorrent.LocalPreferences.LocalPreferencesClass();
let saveWindowSize = function() {};
let loadWindowWidth = function() {};
diff --git a/src/webui/www/private/scripts/preferences.js b/src/webui/www/private/scripts/preferences.js
index 9d21fa4ab..87606bad7 100644
--- a/src/webui/www/private/scripts/preferences.js
+++ b/src/webui/www/private/scripts/preferences.js
@@ -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);
- }
- catch (err) {
- console.error(err);
+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);
+ }
}
- }
-})
+ })
+
+ return exports();
+})();
diff --git a/src/webui/www/private/scripts/progressbar.js b/src/webui/www/private/scripts/progressbar.js
index 959c78be5..18c252840 100644
--- a/src/webui/www/private/scripts/progressbar.js
+++ b/src/webui/www/private/scripts/progressbar.js
@@ -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;
- }
-});
+ };
-function ProgressBar_getValue() {
- return this.vals.value;
-}
+ 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_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_getValue() {
+ return this.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);
+ 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);
+ }
+ }
+
+ 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);
+ }
-let ProgressBars = 0;
+ return exports();
+})();
diff --git a/src/webui/www/private/scripts/prop-files.js b/src/webui/www/private/scripts/prop-files.js
index 485b54f2a..cee8ef857 100644
--- a/src/webui/www/private/scripts/prop-files.js
+++ b/src/webui/www/private/scripts/prop-files.js
@@ -28,647 +28,672 @@
'use strict';
-let is_seed = true;
-this.current_hash = "";
-
-const normalizePriority = function(priority) {
- switch (priority) {
- case FilePriority.Ignored:
- case FilePriority.Normal:
- case FilePriority.High:
- case FilePriority.Maximum:
- case FilePriority.Mixed:
- return priority;
- default:
- return FilePriority.Normal;
- }
-};
+if (window.qBittorrent === undefined) {
+ window.qBittorrent = {};
+}
-const getAllChildren = function(id, fileId) {
- const node = torrentFilesTable.getNode(id);
- if (!node.isFolder) {
+window.qBittorrent.PropFiles = (function() {
+ const exports = function() {
return {
- rowIds: [id],
- fileIds: [fileId]
+ normalizePriority: normalizePriority,
+ isDownloadCheckboxExists: isDownloadCheckboxExists,
+ createDownloadCheckbox: createDownloadCheckbox,
+ updateDownloadCheckbox: updateDownloadCheckbox,
+ isPriorityComboExists: isPriorityComboExists,
+ createPriorityCombo: createPriorityCombo,
+ updatePriorityCombo: updatePriorityCombo,
+ updateData: updateData,
+ collapseIconClicked: collapseIconClicked
};
- }
-
- const rowIds = [];
- const fileIds = [];
+ };
- const getChildFiles = function(node) {
- if (node.isFolder) {
- node.children.each(function(child) {
- getChildFiles(child);
- });
+ const torrentFilesTable = new window.qBittorrent.DynamicTable.TorrentFilesTable();
+ const FilePriority = window.qBittorrent.FileTree.FilePriority;
+ const TriState = window.qBittorrent.FileTree.TriState;
+ let is_seed = true;
+ let current_hash = "";
+
+ const normalizePriority = function(priority) {
+ switch (priority) {
+ case FilePriority.Ignored:
+ case FilePriority.Normal:
+ case FilePriority.High:
+ case FilePriority.Maximum:
+ case FilePriority.Mixed:
+ return priority;
+ default:
+ return FilePriority.Normal;
}
- else {
- rowIds.push(node.data.rowId);
- fileIds.push(node.data.fileId);
+ };
+
+ const getAllChildren = function(id, fileId) {
+ const node = torrentFilesTable.getNode(id);
+ if (!node.isFolder) {
+ return {
+ rowIds: [id],
+ fileIds: [fileId]
+ };
}
+
+ const rowIds = [];
+ const fileIds = [];
+
+ const getChildFiles = function(node) {
+ if (node.isFolder) {
+ node.children.each(function(child) {
+ getChildFiles(child);
+ });
+ }
+ else {
+ rowIds.push(node.data.rowId);
+ fileIds.push(node.data.fileId);
+ }
+ };
+
+ node.children.each(function(child) {
+ getChildFiles(child);
+ });
+
+ return {
+ rowIds: rowIds,
+ fileIds: fileIds
+ };
};
- node.children.each(function(child) {
- getChildFiles(child);
- });
+ const fileCheckboxClicked = function(e) {
+ e.stopPropagation();
- return {
- rowIds: rowIds,
- fileIds: fileIds
+ const checkbox = e.target;
+ const priority = checkbox.checked ? FilePriority.Normal : FilePriority.Ignored;
+ const id = checkbox.get('data-id');
+ const fileId = checkbox.get('data-file-id');
+
+ const rows = getAllChildren(id, fileId);
+
+ setFilePriority(rows.rowIds, rows.fileIds, priority);
+ updateGlobalCheckbox();
};
-};
-const fileCheckboxClicked = function(e) {
- e.stopPropagation();
+ const fileComboboxChanged = function(e) {
+ const combobox = e.target;
+ const priority = combobox.value;
+ const id = combobox.get('data-id');
+ const fileId = combobox.get('data-file-id');
+
+ const rows = getAllChildren(id, fileId);
- const checkbox = e.target;
- const priority = checkbox.checked ? FilePriority.Normal : FilePriority.Ignored;
- const id = checkbox.get('data-id');
- const fileId = checkbox.get('data-file-id');
+ setFilePriority(rows.rowIds, rows.fileIds, priority);
+ updateGlobalCheckbox();
+ };
+
+ const isDownloadCheckboxExists = function(id) {
+ return ($('cbPrio' + id) !== null);
+ };
- const rows = getAllChildren(id, fileId);
+ const createDownloadCheckbox = function(id, fileId, checked) {
+ const checkbox = new Element('input');
+ checkbox.set('type', 'checkbox');
+ checkbox.set('id', 'cbPrio' + id);
+ checkbox.set('data-id', id);
+ checkbox.set('data-file-id', fileId);
+ checkbox.set('class', 'DownloadedCB');
+ checkbox.addEvent('click', fileCheckboxClicked);
+
+ updateCheckbox(checkbox, checked);
+ return checkbox;
+ };
- setFilePriority(rows.rowIds, rows.fileIds, priority);
- updateGlobalCheckbox();
-};
+ const updateDownloadCheckbox = function(id, checked) {
+ const checkbox = $('cbPrio' + id);
+ updateCheckbox(checkbox, checked);
+ };
-const fileComboboxChanged = function(e) {
- const combobox = e.target;
- const priority = combobox.value;
- const id = combobox.get('data-id');
- const fileId = combobox.get('data-file-id');
+ const updateCheckbox = function(checkbox, checked) {
+ switch (checked) {
+ case TriState.Checked:
+ setCheckboxChecked(checkbox);
+ break;
+ case TriState.Unchecked:
+ setCheckboxUnchecked(checkbox);
+ break;
+ case TriState.Partial:
+ setCheckboxPartial(checkbox);
+ break;
+ }
+ }
- const rows = getAllChildren(id, fileId);
+ const isPriorityComboExists = function(id) {
+ return ($('comboPrio' + id) !== null);
+ };
- setFilePriority(rows.rowIds, rows.fileIds, priority);
- updateGlobalCheckbox();
-};
+ const createPriorityOptionElement = function(priority, selected, html) {
+ const elem = new Element('option');
+ elem.set('value', priority.toString());
+ elem.set('html', html);
+ if (selected)
+ elem.setAttribute('selected', '');
+ return elem;
+ };
+
+ const createPriorityCombo = function(id, fileId, selectedPriority) {
+ const select = new Element('select');
+ select.set('id', 'comboPrio' + id);
+ select.set('data-id', id);
+ select.set('data-file-id', fileId);
+ select.set('disabled', is_seed);
+ select.addClass('combo_priority');
+ select.addEvent('change', fileComboboxChanged);
+
+ createPriorityOptionElement(FilePriority.Ignored, (FilePriority.Ignored === selectedPriority), 'QBT_TR(Do not download)QBT_TR[CONTEXT=PropListDelegate]').injectInside(select);
+ createPriorityOptionElement(FilePriority.Normal, (FilePriority.Normal === selectedPriority), 'QBT_TR(Normal)QBT_TR[CONTEXT=PropListDelegate]').injectInside(select);
+ createPriorityOptionElement(FilePriority.High, (FilePriority.High === selectedPriority), 'QBT_TR(High)QBT_TR[CONTEXT=PropListDelegate]').injectInside(select);
+ createPriorityOptionElement(FilePriority.Maximum, (FilePriority.Maximum === selectedPriority), 'QBT_TR(Maximum)QBT_TR[CONTEXT=PropListDelegate]').injectInside(select);
+
+ // "Mixed" priority is for display only; it shouldn't be selectable
+ const mixedPriorityOption = createPriorityOptionElement(FilePriority.Mixed, (FilePriority.Mixed === selectedPriority), 'QBT_TR(Mixed)QBT_TR[CONTEXT=PropListDelegate]');
+ mixedPriorityOption.set('disabled', true);
+ mixedPriorityOption.injectInside(select);
+
+ return select;
+ };
+
+ const updatePriorityCombo = function(id, selectedPriority) {
+ const combobox = $('comboPrio' + id);
+
+ if (parseInt(combobox.value) !== selectedPriority)
+ selectComboboxPriority(combobox, selectedPriority);
+
+ if (combobox.disabled !== is_seed)
+ combobox.disabled = is_seed;
+ };
+
+ const selectComboboxPriority = function(combobox, priority) {
+ const options = combobox.options;
+ for (let i = 0; i < options.length; ++i) {
+ const option = options[i];
+ if (parseInt(option.value) === priority)
+ option.setAttribute('selected', '');
+ else
+ option.removeAttribute('selected');
+ }
+
+ combobox.value = priority;
+ };
-const isDownloadCheckboxExists = function(id) {
- return ($('cbPrio' + id) !== null);
-};
+ const switchCheckboxState = function(e) {
+ e.stopPropagation();
-const createDownloadCheckbox = function(id, fileId, checked) {
- const checkbox = new Element('input');
- checkbox.set('type', 'checkbox');
- checkbox.set('id', 'cbPrio' + id);
- checkbox.set('data-id', id);
- checkbox.set('data-file-id', fileId);
- checkbox.set('class', 'DownloadedCB');
- checkbox.addEvent('click', fileCheckboxClicked);
+ const rowIds = [];
+ const fileIds = [];
+ let priority = FilePriority.Ignored;
+ const checkbox = $('tristate_cb');
- updateCheckbox(checkbox, checked);
- return checkbox;
-};
+ if (checkbox.state === "checked") {
+ setCheckboxUnchecked(checkbox);
+ // set file priority for all checked to Ignored
+ torrentFilesTable.getFilteredAndSortedRows().forEach(function(row) {
+ const rowId = row.rowId;
+ const fileId = row.full_data.fileId;
+ const isChecked = (row.full_data.checked === TriState.Checked);
+ const isFolder = (fileId === -1);
+ if (!isFolder && isChecked) {
+ rowIds.push(rowId);
+ fileIds.push(fileId);
+ }
+ });
+ }
+ else {
+ setCheckboxChecked(checkbox);
+ priority = FilePriority.Normal;
+ // set file priority for all unchecked to Normal
+ torrentFilesTable.getFilteredAndSortedRows().forEach(function(row) {
+ const rowId = row.rowId;
+ const fileId = row.full_data.fileId;
+ const isUnchecked = (row.full_data.checked === TriState.Unchecked);
+ const isFolder = (fileId === -1);
+ if (!isFolder && isUnchecked) {
+ rowIds.push(rowId);
+ fileIds.push(fileId);
+ }
+ });
+ }
-const updateDownloadCheckbox = function(id, checked) {
- const checkbox = $('cbPrio' + id);
- updateCheckbox(checkbox, checked);
-};
+ if (rowIds.length > 0)
+ setFilePriority(rowIds, fileIds, priority);
+ };
-const updateCheckbox = function(checkbox, checked) {
- switch (checked) {
- case TriState.Checked:
+ const updateGlobalCheckbox = function() {
+ const checkbox = $('tristate_cb');
+ if (isAllCheckboxesChecked())
setCheckboxChecked(checkbox);
- break;
- case TriState.Unchecked:
+ else if (isAllCheckboxesUnchecked())
setCheckboxUnchecked(checkbox);
- break;
- case TriState.Partial:
+ else
setCheckboxPartial(checkbox);
- break;
- }
-}
+ };
-const isPriorityComboExists = function(id) {
- return ($('comboPrio' + id) !== null);
-};
-
-const createPriorityOptionElement = function(priority, selected, html) {
- const elem = new Element('option');
- elem.set('value', priority.toString());
- elem.set('html', html);
- if (selected)
- elem.setAttribute('selected', '');
- return elem;
-};
-
-const createPriorityCombo = function(id, fileId, selectedPriority) {
- const select = new Element('select');
- select.set('id', 'comboPrio' + id);
- select.set('data-id', id);
- select.set('data-file-id', fileId);
- select.set('disabled', is_seed);
- select.addClass('combo_priority');
- select.addEvent('change', fileComboboxChanged);
-
- createPriorityOptionElement(FilePriority.Ignored, (FilePriority.Ignored === selectedPriority), 'QBT_TR(Do not download)QBT_TR[CONTEXT=PropListDelegate]').injectInside(select);
- createPriorityOptionElement(FilePriority.Normal, (FilePriority.Normal === selectedPriority), 'QBT_TR(Normal)QBT_TR[CONTEXT=PropListDelegate]').injectInside(select);
- createPriorityOptionElement(FilePriority.High, (FilePriority.High === selectedPriority), 'QBT_TR(High)QBT_TR[CONTEXT=PropListDelegate]').injectInside(select);
- createPriorityOptionElement(FilePriority.Maximum, (FilePriority.Maximum === selectedPriority), 'QBT_TR(Maximum)QBT_TR[CONTEXT=PropListDelegate]').injectInside(select);
-
- // "Mixed" priority is for display only; it shouldn't be selectable
- const mixedPriorityOption = createPriorityOptionElement(FilePriority.Mixed, (FilePriority.Mixed === selectedPriority), 'QBT_TR(Mixed)QBT_TR[CONTEXT=PropListDelegate]');
- mixedPriorityOption.set('disabled', true);
- mixedPriorityOption.injectInside(select);
-
- return select;
-};
-
-const updatePriorityCombo = function(id, selectedPriority) {
- const combobox = $('comboPrio' + id);
-
- if (parseInt(combobox.value) !== selectedPriority)
- selectComboboxPriority(combobox, selectedPriority);
-
- if (combobox.disabled !== is_seed)
- combobox.disabled = is_seed;
-};
-
-const selectComboboxPriority = function(combobox, priority) {
- const options = combobox.options;
- for (let i = 0; i < options.length; ++i) {
- const option = options[i];
- if (parseInt(option.value) === priority)
- option.setAttribute('selected', '');
- else
- option.removeAttribute('selected');
- }
+ const setCheckboxChecked = function(checkbox) {
+ checkbox.state = "checked";
+ checkbox.indeterminate = false;
+ checkbox.checked = true;
+ };
- combobox.value = priority;
-};
-
-const switchCheckboxState = function(e) {
- e.stopPropagation();
-
- const rowIds = [];
- const fileIds = [];
- let priority = FilePriority.Ignored;
- const checkbox = $('tristate_cb');
-
- if (checkbox.state === "checked") {
- setCheckboxUnchecked(checkbox);
- // set file priority for all checked to Ignored
- torrentFilesTable.getFilteredAndSortedRows().forEach(function(row) {
- const rowId = row.rowId;
- const fileId = row.full_data.fileId;
- const isChecked = (row.full_data.checked === TriState.Checked);
- const isFolder = (fileId === -1);
- if (!isFolder && isChecked) {
- rowIds.push(rowId);
- fileIds.push(fileId);
- }
- });
- }
- else {
- setCheckboxChecked(checkbox);
- priority = FilePriority.Normal;
- // set file priority for all unchecked to Normal
- torrentFilesTable.getFilteredAndSortedRows().forEach(function(row) {
- const rowId = row.rowId;
- const fileId = row.full_data.fileId;
- const isUnchecked = (row.full_data.checked === TriState.Unchecked);
- const isFolder = (fileId === -1);
- if (!isFolder && isUnchecked) {
- rowIds.push(rowId);
- fileIds.push(fileId);
- }
- });
- }
+ const setCheckboxUnchecked = function(checkbox) {
+ checkbox.state = "unchecked";
+ checkbox.indeterminate = false;
+ checkbox.checked = false;
+ };
- if (rowIds.length > 0)
- setFilePriority(rowIds, fileIds, priority);
-};
-
-const updateGlobalCheckbox = function() {
- const checkbox = $('tristate_cb');
- if (isAllCheckboxesChecked())
- setCheckboxChecked(checkbox);
- else if (isAllCheckboxesUnchecked())
- setCheckboxUnchecked(checkbox);
- else
- setCheckboxPartial(checkbox);
-};
-
-const setCheckboxChecked = function(checkbox) {
- checkbox.state = "checked";
- checkbox.indeterminate = false;
- checkbox.checked = true;
-};
-
-const setCheckboxUnchecked = function(checkbox) {
- checkbox.state = "unchecked";
- checkbox.indeterminate = false;
- checkbox.checked = false;
-};
-
-const setCheckboxPartial = function(checkbox) {
- checkbox.state = "partial";
- checkbox.indeterminate = true;
-};
-
-const isAllCheckboxesChecked = function() {
- const checkboxes = $$('input.DownloadedCB');
- for (let i = 0; i < checkboxes.length; ++i) {
- if (!checkboxes[i].checked)
- return false;
- }
- return true;
-};
-
-const isAllCheckboxesUnchecked = function() {
- const checkboxes = $$('input.DownloadedCB');
- for (let i = 0; i < checkboxes.length; ++i) {
- if (checkboxes[i].checked)
- return false;
- }
- return true;
-};
-
-const setFilePriority = function(ids, fileIds, priority) {
- if (current_hash === "") return;
-
- clearTimeout(loadTorrentFilesDataTimer);
- new Request({
- url: 'api/v2/torrents/filePrio',
- method: 'post',
- data: {
- 'hash': current_hash,
- 'id': fileIds.join('|'),
- 'priority': priority
- },
- onComplete: function() {
- loadTorrentFilesDataTimer = loadTorrentFilesData.delay(1000);
- }
- }).send();
+ const setCheckboxPartial = function(checkbox) {
+ checkbox.state = "partial";
+ checkbox.indeterminate = true;
+ };
- const ignore = (priority === FilePriority.Ignored);
- ids.forEach(function(_id) {
- torrentFilesTable.setIgnored(_id, ignore);
+ const isAllCheckboxesChecked = function() {
+ const checkboxes = $$('input.DownloadedCB');
+ for (let i = 0; i < checkboxes.length; ++i) {
+ if (!checkboxes[i].checked)
+ return false;
+ }
+ return true;
+ };
- const combobox = $('comboPrio' + _id);
- if (combobox !== null)
- selectComboboxPriority(combobox, priority);
- });
+ const isAllCheckboxesUnchecked = function() {
+ const checkboxes = $$('input.DownloadedCB');
+ for (let i = 0; i < checkboxes.length; ++i) {
+ if (checkboxes[i].checked)
+ return false;
+ }
+ return true;
+ };
- torrentFilesTable.updateTable(false);
-};
+ const setFilePriority = function(ids, fileIds, priority) {
+ if (current_hash === "") return;
-let loadTorrentFilesDataTimer;
-const loadTorrentFilesData = function() {
- if ($('prop_files').hasClass('invisible')
- || $('propertiesPanel_collapseToggle').hasClass('panel-expand')) {
- // Tab changed, don't do anything
- return;
- }
- const new_hash = torrentsTable.getCurrentTorrentHash();
- if (new_hash === "") {
- torrentFilesTable.clear();
clearTimeout(loadTorrentFilesDataTimer);
- loadTorrentFilesDataTimer = loadTorrentFilesData.delay(5000);
- return;
- }
- let loadedNewTorrent = false;
- if (new_hash != current_hash) {
- torrentFilesTable.clear();
- current_hash = new_hash;
- loadedNewTorrent = true;
- }
- const url = new URI('api/v2/torrents/files?hash=' + current_hash);
- new Request.JSON({
- url: url,
- noCache: true,
- method: 'get',
- onComplete: function() {
- clearTimeout(loadTorrentFilesDataTimer);
- loadTorrentFilesDataTimer = loadTorrentFilesData.delay(5000);
- },
- onSuccess: function(files) {
- clearTimeout(torrentFilesFilterInputTimer);
-
- if (files.length === 0) {
- torrentFilesTable.clear();
- }
- else {
- handleNewTorrentFiles(files);
- if (loadedNewTorrent)
- collapseAllNodes();
+ new Request({
+ url: 'api/v2/torrents/filePrio',
+ method: 'post',
+ data: {
+ 'hash': current_hash,
+ 'id': fileIds.join('|'),
+ 'priority': priority
+ },
+ onComplete: function() {
+ loadTorrentFilesDataTimer = loadTorrentFilesData.delay(1000);
}
- }
- }).send();
-};
-
-updateTorrentFilesData = function() {
- clearTimeout(loadTorrentFilesDataTimer);
- loadTorrentFilesData();
-};
-
-const handleNewTorrentFiles = function(files) {
- is_seed = (files.length > 0) ? files[0].is_seed : true;
-
- const rows = files.map(function(file, index) {
- let progress = (file.progress * 100).round(1);
- if ((progress === 100) && (file.progress < 1))
- progress = 99.9;
-
- const name = escapeHtml(file.name);
- const ignore = (file.priority === FilePriority.Ignored);
- const checked = (ignore ? TriState.Unchecked : TriState.Checked);
- const remaining = (ignore ? 0 : (file.size * (1.0 - file.progress)));
- const row = {
- fileId: index,
- checked: checked,
- fileName: name,
- name: fileName(name),
- size: file.size,
- progress: progress,
- priority: normalizePriority(file.priority),
- remaining: remaining,
- availability: file.availability
- };
+ }).send();
- return row;
- });
+ const ignore = (priority === FilePriority.Ignored);
+ ids.forEach(function(_id) {
+ torrentFilesTable.setIgnored(_id, ignore);
- addRowsToTable(rows);
- updateGlobalCheckbox();
-};
+ const combobox = $('comboPrio' + _id);
+ if (combobox !== null)
+ selectComboboxPriority(combobox, priority);
+ });
-const addRowsToTable = function(rows) {
- const selectedFiles = torrentFilesTable.selectedRowsIds();
- let rowId = 0;
+ torrentFilesTable.updateTable(false);
+ };
- const rootNode = new FolderNode();
+ let loadTorrentFilesDataTimer;
+ const loadTorrentFilesData = function() {
+ if ($('prop_files').hasClass('invisible')
+ || $('propertiesPanel_collapseToggle').hasClass('panel-expand')) {
+ // Tab changed, don't do anything
+ return;
+ }
+ const new_hash = torrentsTable.getCurrentTorrentHash();
+ if (new_hash === "") {
+ torrentFilesTable.clear();
+ clearTimeout(loadTorrentFilesDataTimer);
+ loadTorrentFilesDataTimer = loadTorrentFilesData.delay(5000);
+ return;
+ }
+ let loadedNewTorrent = false;
+ if (new_hash != current_hash) {
+ torrentFilesTable.clear();
+ current_hash = new_hash;
+ loadedNewTorrent = true;
+ }
+ const url = new URI('api/v2/torrents/files?hash=' + current_hash);
+ new Request.JSON({
+ url: url,
+ noCache: true,
+ method: 'get',
+ onComplete: function() {
+ clearTimeout(loadTorrentFilesDataTimer);
+ loadTorrentFilesDataTimer = loadTorrentFilesData.delay(5000);
+ },
+ onSuccess: function(files) {
+ clearTimeout(torrentFilesFilterInputTimer);
+
+ if (files.length === 0) {
+ torrentFilesTable.clear();
+ }
+ else {
+ handleNewTorrentFiles(files);
+ if (loadedNewTorrent)
+ collapseAllNodes();
+ }
+ }
+ }).send();
+ };
- rows.forEach(function(row) {
- let parent = rootNode;
- const pathFolders = row.fileName.split(PathSeparator);
- pathFolders.pop();
- pathFolders.forEach(function(folderName) {
- if (folderName === '.unwanted')
- return;
+ const updateData = function() {
+ clearTimeout(loadTorrentFilesDataTimer);
+ loadTorrentFilesData();
+ };
+
+ const handleNewTorrentFiles = function(files) {
+ is_seed = (files.length > 0) ? files[0].is_seed : true;
+
+ const rows = files.map(function(file, index) {
+ let progress = (file.progress * 100).round(1);
+ if ((progress === 100) && (file.progress < 1))
+ progress = 99.9;
+
+ const name = window.qBittorrent.Misc.escapeHtml(file.name);
+ const ignore = (file.priority === FilePriority.Ignored);
+ const checked = (ignore ? TriState.Unchecked : TriState.Checked);
+ const remaining = (ignore ? 0 : (file.size * (1.0 - file.progress)));
+ const row = {
+ fileId: index,
+ checked: checked,
+ fileName: name,
+ name: window.qBittorrent.Filesystem.fileName(name),
+ size: file.size,
+ progress: progress,
+ priority: normalizePriority(file.priority),
+ remaining: remaining,
+ availability: file.availability
+ };
+
+ return row;
+ });
+
+ addRowsToTable(rows);
+ updateGlobalCheckbox();
+ };
- let parentNode = null;
- if (parent.children !== null) {
- for (let i = 0; i < parent.children.length; ++i) {
- const childFolder = parent.children[i];
- if (childFolder.name === folderName) {
- parentNode = childFolder;
- break;
+ const addRowsToTable = function(rows) {
+ const selectedFiles = torrentFilesTable.selectedRowsIds();
+ let rowId = 0;
+
+ const rootNode = new window.qBittorrent.FileTree.FolderNode();
+
+ rows.forEach(function(row) {
+ let parent = rootNode;
+ const pathFolders = row.fileName.split(window.qBittorrent.Filesystem.PathSeparator);
+ pathFolders.pop();
+ pathFolders.forEach(function(folderName) {
+ if (folderName === '.unwanted')
+ return;
+
+ let parentNode = null;
+ if (parent.children !== null) {
+ for (let i = 0; i < parent.children.length; ++i) {
+ const childFolder = parent.children[i];
+ if (childFolder.name === folderName) {
+ parentNode = childFolder;
+ break;
+ }
}
}
- }
- if (parentNode === null) {
- parentNode = new FolderNode();
- parentNode.name = folderName;
- parentNode.rowId = rowId;
- parentNode.root = parent;
- parent.addChild(parentNode);
-
- ++rowId;
- }
+ if (parentNode === null) {
+ parentNode = new window.qBittorrent.FileTree.FolderNode();
+ parentNode.name = folderName;
+ parentNode.rowId = rowId;
+ parentNode.root = parent;
+ parent.addChild(parentNode);
+
+ ++rowId;
+ }
- parent = parentNode;
- });
+ parent = parentNode;
+ });
- const isChecked = row.checked ? TriState.Checked : TriState.Unchecked;
- const remaining = (row.priority === FilePriority.Ignored) ? 0 : row.remaining;
- const childNode = new FileNode();
- childNode.name = row.name;
- childNode.rowId = rowId;
- childNode.size = row.size;
- childNode.checked = isChecked;
- childNode.remaining = remaining;
- childNode.progress = row.progress;
- childNode.priority = row.priority;
- childNode.availability = row.availability;
- childNode.root = parent;
- childNode.data = row;
- parent.addChild(childNode);
-
- ++rowId;
- }.bind(this));
-
- torrentFilesTable.populateTable(rootNode);
- torrentFilesTable.updateTable(false);
- torrentFilesTable.altRow();
-
- if (selectedFiles.length > 0)
- torrentFilesTable.reselectRows(selectedFiles);
-};
-
-const collapseIconClicked = function(event) {
- const id = event.get("data-id");
- const node = torrentFilesTable.getNode(id);
- const isCollapsed = (event.parentElement.get("data-collapsed") === "true");
-
- if (isCollapsed)
- expandNode(node);
- else
- collapseNode(node);
-};
-
-const filesPriorityMenuClicked = function(priority) {
- const selectedRows = torrentFilesTable.selectedRowsIds();
- if (selectedRows.length === 0) return;
-
- const rowIds = [];
- const fileIds = [];
- selectedRows.forEach(function(rowId) {
- const elem = $('comboPrio' + rowId);
- rowIds.push(rowId);
- fileIds.push(elem.get("data-file-id"));
- });
+ const isChecked = row.checked ? TriState.Checked : TriState.Unchecked;
+ const remaining = (row.priority === FilePriority.Ignored) ? 0 : row.remaining;
+ const childNode = new window.qBittorrent.FileTree.FileNode();
+ childNode.name = row.name;
+ childNode.rowId = rowId;
+ childNode.size = row.size;
+ childNode.checked = isChecked;
+ childNode.remaining = remaining;
+ childNode.progress = row.progress;
+ childNode.priority = row.priority;
+ childNode.availability = row.availability;
+ childNode.root = parent;
+ childNode.data = row;
+ parent.addChild(childNode);
+
+ ++rowId;
+ }.bind(this));
+
+ torrentFilesTable.populateTable(rootNode);
+ torrentFilesTable.updateTable(false);
+ torrentFilesTable.altRow();
+
+ if (selectedFiles.length > 0)
+ torrentFilesTable.reselectRows(selectedFiles);
+ };
- const uniqueRowIds = {};
- const uniqueFileIds = {};
- for (let i = 0; i < rowIds.length; ++i) {
- const rows = getAllChildren(rowIds[i], fileIds[i]);
- rows.rowIds.forEach(function(rowId) {
- uniqueRowIds[rowId] = true;
- });
- rows.fileIds.forEach(function(fileId) {
- uniqueFileIds[fileId] = true;
+ const collapseIconClicked = function(event) {
+ const id = event.get("data-id");
+ const node = torrentFilesTable.getNode(id);
+ const isCollapsed = (event.parentElement.get("data-collapsed") === "true");
+
+ if (isCollapsed)
+ expandNode(node);
+ else
+ collapseNode(node);
+ };
+
+ const filesPriorityMenuClicked = function(priority) {
+ const selectedRows = torrentFilesTable.selectedRowsIds();
+ if (selectedRows.length === 0) return;
+
+ const rowIds = [];
+ const fileIds = [];
+ selectedRows.forEach(function(rowId) {
+ const elem = $('comboPrio' + rowId);
+ rowIds.push(rowId);
+ fileIds.push(elem.get("data-file-id"));
});
- }
- setFilePriority(Object.keys(uniqueRowIds), Object.keys(uniqueFileIds), priority);
-};
+ const uniqueRowIds = {};
+ const uniqueFileIds = {};
+ for (let i = 0; i < rowIds.length; ++i) {
+ const rows = getAllChildren(rowIds[i], fileIds[i]);
+ rows.rowIds.forEach(function(rowId) {
+ uniqueRowIds[rowId] = true;
+ });
+ rows.fileIds.forEach(function(fileId) {
+ uniqueFileIds[fileId] = true;
+ });
+ }
-const torrentFilesContextMenu = new ContextMenu({
- targets: '#torrentFilesTableDiv tr',
- menu: 'torrentFilesMenu',
- actions: {
+ setFilePriority(Object.keys(uniqueRowIds), Object.keys(uniqueFileIds), priority);
+ };
- FilePrioIgnore: function(element, ref) {
- filesPriorityMenuClicked(FilePriority.Ignored);
- },
- FilePrioNormal: function(element, ref) {
- filesPriorityMenuClicked(FilePriority.Normal);
+ const torrentFilesContextMenu = new window.qBittorrent.ContextMenu.ContextMenu({
+ targets: '#torrentFilesTableDiv tr',
+ menu: 'torrentFilesMenu',
+ actions: {
+
+ FilePrioIgnore: function(element, ref) {
+ filesPriorityMenuClicked(FilePriority.Ignored);
+ },
+ FilePrioNormal: function(element, ref) {
+ filesPriorityMenuClicked(FilePriority.Normal);
+ },
+ FilePrioHigh: function(element, ref) {
+ filesPriorityMenuClicked(FilePriority.High);
+ },
+ FilePrioMaximum: function(element, ref) {
+ filesPriorityMenuClicked(FilePriority.Maximum);
+ }
},
- FilePrioHigh: function(element, ref) {
- filesPriorityMenuClicked(FilePriority.High);
+ offsets: {
+ x: -15,
+ y: 2
},
- FilePrioMaximum: function(element, ref) {
- filesPriorityMenuClicked(FilePriority.Maximum);
+ onShow: function() {
+ if (is_seed)
+ this.hideItem('FilePrio');
+ else
+ this.showItem('FilePrio');
}
- },
- offsets: {
- x: -15,
- y: 2
- },
- onShow: function() {
- if (is_seed)
- this.hideItem('FilePrio');
- else
- this.showItem('FilePrio');
+ });
+
+ torrentFilesTable.setup('torrentFilesTableDiv', 'torrentFilesTableFixedHeaderDiv', torrentFilesContextMenu);
+ // inject checkbox into table header
+ const tableHeaders = $$('#torrentFilesTableFixedHeaderDiv .dynamicTableHeader th');
+ if (tableHeaders.length > 0) {
+ const checkbox = new Element('input');
+ checkbox.set('type', 'checkbox');
+ checkbox.set('id', 'tristate_cb');
+ checkbox.addEvent('click', switchCheckboxState);
+
+ const checkboxTH = tableHeaders[0];
+ checkbox.injectInside(checkboxTH);
}
-});
-
-torrentFilesTable.setup('torrentFilesTableDiv', 'torrentFilesTableFixedHeaderDiv', torrentFilesContextMenu);
-// inject checkbox into table header
-const tableHeaders = $$('#torrentFilesTableFixedHeaderDiv .dynamicTableHeader th');
-if (tableHeaders.length > 0) {
- const checkbox = new Element('input');
- checkbox.set('type', 'checkbox');
- checkbox.set('id', 'tristate_cb');
- checkbox.addEvent('click', switchCheckboxState);
-
- const checkboxTH = tableHeaders[0];
- checkbox.injectInside(checkboxTH);
-}
-// default sort by name column
-if (torrentFilesTable.getSortedColumn() === null)
- torrentFilesTable.setSortedColumn('name');
-
-let prevTorrentFilesFilterValue;
-let torrentFilesFilterInputTimer = null;
-// listen for changes to torrentFilesFilterInput
-$('torrentFilesFilterInput').addEvent('input', function() {
- const value = $('torrentFilesFilterInput').get("value");
- if (value !== prevTorrentFilesFilterValue) {
- prevTorrentFilesFilterValue = value;
- torrentFilesTable.setFilter(value);
- clearTimeout(torrentFilesFilterInputTimer);
- torrentFilesFilterInputTimer = setTimeout(function() {
- if (current_hash === "") return;
- torrentFilesTable.updateTable(false);
-
- if (value.trim() === "")
- collapseAllNodes();
- else
- expandAllNodes();
- }, 400);
+ // default sort by name column
+ if (torrentFilesTable.getSortedColumn() === null)
+ torrentFilesTable.setSortedColumn('name');
+
+ let prevTorrentFilesFilterValue;
+ let torrentFilesFilterInputTimer = null;
+ // listen for changes to torrentFilesFilterInput
+ $('torrentFilesFilterInput').addEvent('input', function() {
+ const value = $('torrentFilesFilterInput').get("value");
+ if (value !== prevTorrentFilesFilterValue) {
+ prevTorrentFilesFilterValue = value;
+ torrentFilesTable.setFilter(value);
+ clearTimeout(torrentFilesFilterInputTimer);
+ torrentFilesFilterInputTimer = setTimeout(function() {
+ if (current_hash === "") return;
+ torrentFilesTable.updateTable(false);
+
+ if (value.trim() === "")
+ collapseAllNodes();
+ else
+ expandAllNodes();
+ }, 400);
+ }
+ });
+
+ /**
+ * Show/hide a node's row
+ */
+ const _hideNode = function(node, shouldHide) {
+ const span = $('filesTablefileName' + node.rowId);
+ // span won't exist if row has been filtered out
+ if (span === null)
+ return;
+ const rowElem = span.parentElement.parentElement;
+ if (shouldHide)
+ rowElem.addClass("invisible");
+ else
+ rowElem.removeClass("invisible");
}
-});
-/**
- * Show/hide a node's row
- */
-const _hideNode = function(node, shouldHide) {
- const span = $('filesTablefileName' + node.rowId);
- // span won't exist if row has been filtered out
- if (span === null)
- return;
- const rowElem = span.parentElement.parentElement;
- if (shouldHide)
- rowElem.addClass("invisible");
- else
- rowElem.removeClass("invisible");
-}
+ /**
+ * Update a node's collapsed state and icon
+ */
+ const _updateNodeState = function(node, isCollapsed) {
+ const span = $('filesTablefileName' + node.rowId);
+ // span won't exist if row has been filtered out
+ if (span === null)
+ return;
+ const td = span.parentElement;
+ const rowElem = td.parentElement;
-/**
- * Update a node's collapsed state and icon
- */
-const _updateNodeState = function(node, isCollapsed) {
- const span = $('filesTablefileName' + node.rowId);
- // span won't exist if row has been filtered out
- if (span === null)
- return;
- const td = span.parentElement;
- const rowElem = td.parentElement;
-
- // store collapsed state
- td.set("data-collapsed", isCollapsed);
-
- // rotate the collapse icon
- const collapseIcon = td.getElementsByClassName("filesTableCollapseIcon")[0];
- if (isCollapsed)
- collapseIcon.addClass("rotate");
- else
- collapseIcon.removeClass("rotate");
-}
+ // store collapsed state
+ td.set("data-collapsed", isCollapsed);
-const _isCollapsed = function(node) {
- const span = $('filesTablefileName' + node.rowId);
- if (span === null)
- return true;
+ // rotate the collapse icon
+ const collapseIcon = td.getElementsByClassName("filesTableCollapseIcon")[0];
+ if (isCollapsed)
+ collapseIcon.addClass("rotate");
+ else
+ collapseIcon.removeClass("rotate");
+ }
- const td = span.parentElement;
- return (td.get("data-collapsed") === "true");
-};
+ const _isCollapsed = function(node) {
+ const span = $('filesTablefileName' + node.rowId);
+ if (span === null)
+ return true;
-const expandNode = function(node) {
- _collapseNode(node, false, false, false);
- torrentFilesTable.altRow();
-};
+ const td = span.parentElement;
+ return (td.get("data-collapsed") === "true");
+ };
-const collapseNode = function(node) {
- _collapseNode(node, true, false, false);
- torrentFilesTable.altRow();
-};
+ const expandNode = function(node) {
+ _collapseNode(node, false, false, false);
+ torrentFilesTable.altRow();
+ };
-const expandAllNodes = function() {
- const root = torrentFilesTable.getRoot();
- root.children.each(function(node) {
- node.children.each(function(child) {
- _collapseNode(child, false, true, false);
+ const collapseNode = function(node) {
+ _collapseNode(node, true, false, false);
+ torrentFilesTable.altRow();
+ };
+
+ const expandAllNodes = function() {
+ const root = torrentFilesTable.getRoot();
+ root.children.each(function(node) {
+ node.children.each(function(child) {
+ _collapseNode(child, false, true, false);
+ });
});
- });
- torrentFilesTable.altRow();
-};
+ torrentFilesTable.altRow();
+ };
-const collapseAllNodes = function() {
- const root = torrentFilesTable.getRoot();
- root.children.each(function(node) {
- node.children.each(function(child) {
- _collapseNode(child, true, true, false);
+ const collapseAllNodes = function() {
+ const root = torrentFilesTable.getRoot();
+ root.children.each(function(node) {
+ node.children.each(function(child) {
+ _collapseNode(child, true, true, false);
+ });
});
- });
- torrentFilesTable.altRow();
-}
+ torrentFilesTable.altRow();
+ }
-/**
- * Collapses a folder node with the option to recursively collapse all children
- * @param {FolderNode} node the node to collapse/expand
- * @param {boolean} shouldCollapse true if the node should be collapsed, false if it should be expanded
- * @param {boolean} applyToChildren true if the node's children should also be collapsed, recursively
- * @param {boolean} isChildNode true if the current node is a child of the original node we collapsed/expanded
- */
-const _collapseNode = function(node, shouldCollapse, applyToChildren, isChildNode) {
- if (!node.isFolder)
- return;
+ /**
+ * Collapses a folder node with the option to recursively collapse all children
+ * @param {FolderNode} node the node to collapse/expand
+ * @param {boolean} shouldCollapse true if the node should be collapsed, false if it should be expanded
+ * @param {boolean} applyToChildren true if the node's children should also be collapsed, recursively
+ * @param {boolean} isChildNode true if the current node is a child of the original node we collapsed/expanded
+ */
+ const _collapseNode = function(node, shouldCollapse, applyToChildren, isChildNode) {
+ if (!node.isFolder)
+ return;
- const shouldExpand = !shouldCollapse;
- const isNodeCollapsed = _isCollapsed(node);
- const nodeInCorrectState = ((shouldCollapse && isNodeCollapsed) || (shouldExpand && !isNodeCollapsed));
- const canSkipNode = (isChildNode && (!applyToChildren || nodeInCorrectState));
- if (!isChildNode || applyToChildren || !canSkipNode)
- _updateNodeState(node, shouldCollapse);
+ const shouldExpand = !shouldCollapse;
+ const isNodeCollapsed = _isCollapsed(node);
+ const nodeInCorrectState = ((shouldCollapse && isNodeCollapsed) || (shouldExpand && !isNodeCollapsed));
+ const canSkipNode = (isChildNode && (!applyToChildren || nodeInCorrectState));
+ if (!isChildNode || applyToChildren || !canSkipNode)
+ _updateNodeState(node, shouldCollapse);
- node.children.each(function(child) {
- _hideNode(child, shouldCollapse);
+ node.children.each(function(child) {
+ _hideNode(child, shouldCollapse);
- if (!child.isFolder)
- return;
+ if (!child.isFolder)
+ return;
- // don't expand children that have been independently collapsed, unless applyToChildren is true
- const shouldExpandChildren = (shouldExpand && applyToChildren);
- const isChildCollapsed = _isCollapsed(child);
- if (!shouldExpandChildren && isChildCollapsed)
- return;
+ // don't expand children that have been independently collapsed, unless applyToChildren is true
+ const shouldExpandChildren = (shouldExpand && applyToChildren);
+ const isChildCollapsed = _isCollapsed(child);
+ if (!shouldExpandChildren && isChildCollapsed)
+ return;
- _collapseNode(child, shouldCollapse, applyToChildren, true);
- });
-};
+ _collapseNode(child, shouldCollapse, applyToChildren, true);
+ });
+ };
+
+ return exports();
+})();
diff --git a/src/webui/www/private/scripts/prop-general.js b/src/webui/www/private/scripts/prop-general.js
index 2349c6b7a..445893b88 100644
--- a/src/webui/www/private/scripts/prop-general.js
+++ b/src/webui/www/private/scripts/prop-general.js
@@ -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', '');
-};
-
-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);
-
- $('eta').set('html', 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", 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();
- }
+if (window.qBittorrent === undefined) {
+ window.qBittorrent = {};
+}
+
+window.qBittorrent.PropGeneral = (function() {
+ const exports = function() {
+ return {
+ updateData: updateData
+ };
+ };
+
+ 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', '');
+ };
+
+ 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);
+
+ $('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();
+ };
-updateTorrentData = function() {
- clearTimeout(loadTorrentDataTimer);
- loadTorrentData();
-};
+ return exports();
+})();
diff --git a/src/webui/www/private/scripts/prop-peers.js b/src/webui/www/private/scripts/prop-peers.js
index 08f10f5f4..c1bba676a 100644
--- a/src/webui/www/private/scripts/prop-peers.js
+++ b/src/webui/www/private/scripts/prop-peers.js
@@ -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)
- torrentPeersTable.clear();
- if (response['rid'])
- syncTorrentPeersLastResponseId = response['rid'];
- if (response['peers']) {
- for (const key in response['peers']) {
- response['peers'][key]['rowId'] = key;
+ 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'] = escapeHtml(response['peers'][key]['client']);
+ if (response['peers'][key]['client'])
+ response['peers'][key]['client'] = window.qBittorrent.Misc.escapeHtml(response['peers'][key]['client']);
- torrentPeersTable.updateRowData(response['peers'][key]);
+ 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');
+ 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();
}
}
- else {
- torrentPeersTable.clear();
+ }).send();
+ };
+
+ 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();
+ }
}
- }
- }).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) {
+ offsets: {
+ x: -15,
+ y: 2
+ },
+ onShow: function() {
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();
+
+ if (selectedPeers.length >= 1) {
+ this.showItem('copyPeer');
+ this.showItem('banPeer');
+ }
+ else {
+ this.hideItem('copyPeer');
+ this.hideItem('banPeer');
}
}
- },
- 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');
+ });
+
+ new ClipboardJS('#CopyPeerInfo', {
+ text: function(trigger) {
+ return torrentPeersTable.selectedRowsIds().join("\n");
}
- }
-});
+ });
-new ClipboardJS('#CopyPeerInfo', {
- text: function(trigger) {
- return torrentPeersTable.selectedRowsIds().join("\n");
- }
-});
+ torrentPeersTable.setup('torrentPeersTableDiv', 'torrentPeersTableFixedHeaderDiv', torrentPeersContextMenu);
-torrentPeersTable.setup('torrentPeersTableDiv', 'torrentPeersTableFixedHeaderDiv', torrentPeersContextMenu);
+ return exports();
+})();
diff --git a/src/webui/www/private/scripts/prop-trackers.js b/src/webui/www/private/scripts/prop-trackers.js
index 2aace0505..315ee8b73 100644
--- a/src/webui/www/private/scripts/prop-trackers.js
+++ b/src/webui/www/private/scripts/prop-trackers.js
@@ -28,195 +28,211 @@
'use strict';
-this.current_hash = "";
-
-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() {
+if (window.qBittorrent === undefined) {
+ window.qBittorrent = {};
+}
+
+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 = 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: window.qBittorrent.Misc.escapeHtml(tracker.msg)
+ };
+
+ torrentTrackersTable.updateRowData(row);
+ });
+
+ torrentTrackersTable.updateTable(false);
+ torrentTrackersTable.altRow();
+
+ if (selectedTrackers.length > 0)
+ torrentTrackersTable.reselectRows(selectedTrackers);
+ }
+ }
+ }).send();
+ };
- 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;
- }
-
- 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)
- };
-
- torrentTrackersTable.updateRowData(row);
- });
-
- torrentTrackersTable.updateTable(false);
- torrentTrackersTable.altRow();
-
- if (selectedTrackers.length > 0)
- torrentTrackersTable.reselectRows(selectedTrackers);
+ 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);
}
- }
- }).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);
+ offsets: {
+ x: -15,
+ y: 2
},
- RemoveTracker: function(element, ref) {
- removeTrackerFN(element);
+ 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');
+ }
}
- },
- 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();
+ }
+ });
+ };
+
+ const editTrackerFN = function(element) {
+ if (current_hash.length === 0) return;
+
+ 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();
+ }
});
+ };
- 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 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 editTrackerFN = function(element) {
- if (current_hash.length === 0) return;
-
- 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() {
+ updateData();
+ }
+ }).send();
+ };
+
+ new ClipboardJS('#CopyTrackerUrl', {
+ text: function(trigger) {
+ return torrentTrackersTable.selectedRowsIds().join("\n");
}
});
-};
-
-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);
-torrentTrackersTable.setup('torrentTrackersTableDiv', 'torrentTrackersTableFixedHeaderDiv', torrentTrackersContextMenu);
+ return exports();
+})();
diff --git a/src/webui/www/private/scripts/prop-webseeds.js b/src/webui/www/private/scripts/prop-webseeds.js
index bf270bfa0..6f6884d03 100644
--- a/src/webui/www/private/scripts/prop-webseeds.js
+++ b/src/webui/www/private/scripts/prop-webseeds.js
@@ -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);
- return true;
- }
- return false;
- },
+ initialize: function() {},
- 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;
- },
+ setup: function(table) {
+ this.table = $(table);
+ this.rows = new Hash();
+ },
- 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);
- },
-});
+ removeRow: function(url) {
+ if (this.rows.has(url)) {
+ const tr = this.rows.get(url);
+ tr.dispose();
+ this.rows.erase(url);
+ return true;
+ }
+ return false;
+ },
-this.current_hash = "";
+ removeAllRows: function() {
+ this.rows.each(function(tr, url) {
+ this.removeRow(url);
+ }.bind(this));
+ },
-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);
+ 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;
},
- 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);
- });
+
+ insertRow: function(row) {
+ const url = row[0];
+ if (this.rows.has(url)) {
+ const tableRow = this.rows.get(url);
+ this.updateRow(tableRow, row);
+ return;
}
- else {
- wsTable.removeAllRows();
+ //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);
+ },
+ });
+
+ let 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;
}
- }).send();
-};
+ 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();
+ };
+
+ const updateData = function() {
+ clearTimeout(loadWebSeedsDataTimer);
+ loadWebSeedsData();
+ };
-updateWebSeedsData = function() {
- clearTimeout(loadWebSeedsDataTimer);
- loadWebSeedsData();
-};
+ const wsTable = new webseedsDynTable();
+ wsTable.setup($('webseedsTable'));
-const wsTable = new webseedsDynTable();
-wsTable.setup($('webseedsTable'));
+ return exports();
+})();
diff --git a/src/webui/www/private/setlocation.html b/src/webui/www/private/setlocation.html
index 9446d166f..d42a7b137 100644
--- a/src/webui/www/private/setlocation.html
+++ b/src/webui/www/private/setlocation.html
@@ -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) {
diff --git a/src/webui/www/private/shareratio.html b/src/webui/www/private/shareratio.html
index f93a36117..b3166af2f 100644
--- a/src/webui/www/private/shareratio.html
+++ b/src/webui/www/private/shareratio.html
@@ -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])
};
diff --git a/src/webui/www/private/upload.html b/src/webui/www/private/upload.html
index adbf64d94..6592bdd4a 100644
--- a/src/webui/www/private/upload.html
+++ b/src/webui/www/private/upload.html
@@ -23,7 +23,7 @@
|
-
+
@@ -51,7 +51,7 @@
|
@@ -29,41 +29,55 @@
diff --git a/src/webui/www/private/views/preferences.html b/src/webui/www/private/views/preferences.html
index e999ab0aa..a09b0881d 100644
--- a/src/webui/www/private/views/preferences.html
+++ b/src/webui/www/private/views/preferences.html
@@ -85,7 +85,7 @@
|
-
+
|
@@ -94,7 +94,7 @@
|
-
+
|
@@ -103,7 +103,7 @@
|
-
+
|
@@ -128,13 +128,13 @@
| |
|
@@ -144,7 +144,7 @@