Browse Source

Merge pull request #11103 from Piccirello/webui-explicit-export

Move JavaScript code into explicit namespaces
adaptive-webui-19844
Mike Tzou 5 years ago committed by GitHub
parent
commit
209831d3b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      src/webui/www/private/addpeers.html
  2. 4
      src/webui/www/private/download.html
  3. 14
      src/webui/www/private/newcategory.html
  4. 4
      src/webui/www/private/newtag.html
  5. 83
      src/webui/www/private/scripts/client.js
  6. 942
      src/webui/www/private/scripts/contextmenu.js
  7. 175
      src/webui/www/private/scripts/download.js
  8. 3519
      src/webui/www/private/scripts/dynamicTable.js
  9. 306
      src/webui/www/private/scripts/file-tree.js
  10. 69
      src/webui/www/private/scripts/filesystem.js
  11. 312
      src/webui/www/private/scripts/misc.js
  12. 2
      src/webui/www/private/scripts/mocha-init.js
  13. 44
      src/webui/www/private/scripts/preferences.js
  14. 219
      src/webui/www/private/scripts/progressbar.js
  15. 1171
      src/webui/www/private/scripts/prop-files.js
  16. 344
      src/webui/www/private/scripts/prop-general.js
  17. 266
      src/webui/www/private/scripts/prop-peers.js
  18. 372
      src/webui/www/private/scripts/prop-trackers.js
  19. 202
      src/webui/www/private/scripts/prop-webseeds.js
  20. 2
      src/webui/www/private/setlocation.html
  21. 4
      src/webui/www/private/shareratio.html
  22. 4
      src/webui/www/private/upload.html
  23. 34
      src/webui/www/private/views/about.html
  24. 64
      src/webui/www/private/views/aboutToolbar.html
  25. 145
      src/webui/www/private/views/filters.html
  26. 82
      src/webui/www/private/views/installsearchplugin.html
  27. 2027
      src/webui/www/private/views/preferences.html
  28. 54
      src/webui/www/private/views/preferencesToolbar.html
  29. 8
      src/webui/www/private/views/properties.html
  30. 1007
      src/webui/www/private/views/search.html
  31. 283
      src/webui/www/private/views/searchplugins.html
  32. 150
      src/webui/www/private/views/transferlist.html

2
src/webui/www/private/addpeers.html

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

4
src/webui/www/private/download.html

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

14
src/webui/www/private/newcategory.html

@ -30,18 +30,18 @@ @@ -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 @@ @@ -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;

4
src/webui/www/private/newtag.html

@ -30,8 +30,8 @@ @@ -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]';

83
src/webui/www/private/scripts/client.js

@ -24,21 +24,10 @@ @@ -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() { @@ -365,12 +354,12 @@ window.addEvent('load', function() {
const create_link = function(hash, text, count) {
const html = '<a href="#" onclick="setCategoryFilter(' + hash + ');return false;">'
+ '<img src="images/qbt-theme/inode-directory.svg"/>'
+ escapeHtml(text) + ' (' + count + ')' + '</a>';
+ window.qBittorrent.Misc.escapeHtml(text) + ' (' + count + ')' + '</a>';
const el = new Element('li', {
id: hash,
html: html
});
categoriesFilterContextMenu.addTarget(el);
window.qBittorrent.Filters.categoriesFilterContextMenu.addTarget(el);
return el;
};
@ -422,12 +411,12 @@ window.addEvent('load', function() { @@ -422,12 +411,12 @@ window.addEvent('load', function() {
const createLink = function(hash, text, count) {
const html = '<a href="#" onclick="setTagFilter(' + hash + ');return false;">'
+ '<img src="images/qbt-theme/inode-directory.svg"/>'
+ escapeHtml(text) + ' (' + count + ')' + '</a>';
+ window.qBittorrent.Misc.escapeHtml(text) + ' (' + count + ')' + '</a>';
const el = new Element('li', {
id: hash,
html: html
});
tagsFilterContextMenu.addTarget(el);
window.qBittorrent.Filters.tagsFilterContextMenu.addTarget(el);
return el;
};
@ -579,11 +568,11 @@ window.addEvent('load', function() { @@ -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() { @@ -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() { @@ -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() { @@ -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) {

942
src/webui/www/private/scripts/contextmenu.js

@ -28,497 +28,515 @@ @@ -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: '<a href="javascript:torrentNewCategoryFN();"><img src="images/qbt-theme/list-add.svg" alt="QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]</a>'
}));
categoryList.appendChild(new Element('li', {
html: '<a href="javascript:torrentSetCategoryFN(0);"><img src="images/qbt-theme/edit-clear.svg" alt="QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]</a>'
}));
const sortedCategories = [];
Object.each(category_list, function(category) {
sortedCategories.push(category.name);
});
sortedCategories.sort();
let first = true;
Object.each(sortedCategories, function(categoryName) {
const categoryHash = genHash(categoryName);
const el = new Element('li', {
html: '<a href="javascript:torrentSetCategoryFN(\'' + categoryHash + '\');"><img src="images/qbt-theme/inode-directory.svg"/> ' + escapeHtml(categoryName) + '</a>'
});
if (first) {
el.addClass('separator');
first = false;
this.showItem('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: '<a href="javascript:torrentAddTagsFN();">'
+ '<img src="images/qbt-theme/list-add.svg" alt="QBT_TR(Add...)QBT_TR[CONTEXT=TransferListWidget]"/>'
+ ' QBT_TR(Add...)QBT_TR[CONTEXT=TransferListWidget]'
+ '</a>'
}));
contextTagList.appendChild(new Element('li', {
html: '<a href="javascript:torrentRemoveAllTagsFN();">'
+ '<img src="images/qbt-theme/edit-clear.svg" alt="QBT_TR(Remove All)QBT_TR[CONTEXT=TransferListWidget]"/>'
+ ' QBT_TR(Remove All)QBT_TR[CONTEXT=TransferListWidget]'
+ '</a>'
}));
const sortedTags = [];
for (const key in tagList)
sortedTags.push(tagList[key].name);
sortedTags.sort();
for (let i = 0; i < sortedTags.length; ++i) {
const tagName = sortedTags[i];
const tagHash = genHash(tagName);
const el = new Element('li', {
html: '<a href="#Tag/' + tagHash + '" onclick="event.preventDefault(); torrentSetTagsFN(\'' + tagHash + '\', !event.currentTarget.getElement(\'input[type=checkbox]\').checked);">'
+ '<input type="checkbox" onclick="this.checked = !this.checked;"> ' + escapeHtml(tagName)
+ '</a>'
this.showItem('start');
this.showItem('pause');
this.showItem('forceStart');
if (all_are_paused)
this.hideItem('pause');
else if (all_are_force_start)
this.hideItem('forceStart');
else if (!there_are_paused && !there_are_force_start)
this.hideItem('start');
if (!all_are_auto_tmm && there_are_auto_tmm) {
this.hideItem('autoTorrentManagement');
}
else {
this.showItem('autoTorrentManagement');
this.setItemChecked('autoTorrentManagement', all_are_auto_tmm);
}
const contextTagList = $('contextTagList');
for (const tagHash in tagList) {
const checkbox = contextTagList.getElement('a[href=#Tag/' + tagHash + '] input[type=checkbox]');
const checkboxState = tagsSelectionState[tagHash];
checkbox.indeterminate = checkboxState.indeterminate;
checkbox.checked = checkboxState.checked;
}
},
updateCategoriesSubMenu: function(category_list) {
const categoryList = $('contextCategoryList');
categoryList.empty();
categoryList.appendChild(new Element('li', {
html: '<a href="javascript:torrentNewCategoryFN();"><img src="images/qbt-theme/list-add.svg" alt="QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]</a>'
}));
categoryList.appendChild(new Element('li', {
html: '<a href="javascript:torrentSetCategoryFN(0);"><img src="images/qbt-theme/edit-clear.svg" alt="QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]</a>'
}));
const sortedCategories = [];
Object.each(category_list, function(category) {
sortedCategories.push(category.name);
});
if (i === 0)
el.addClass('separator');
contextTagList.appendChild(el);
sortedCategories.sort();
let first = true;
Object.each(sortedCategories, function(categoryName) {
const categoryHash = genHash(categoryName);
const el = new Element('li', {
html: '<a href="javascript:torrentSetCategoryFN(\'' + categoryHash + '\');"><img src="images/qbt-theme/inode-directory.svg"/> ' + window.qBittorrent.Misc.escapeHtml(categoryName) + '</a>'
});
if (first) {
el.addClass('separator');
first = false;
}
categoryList.appendChild(el);
});
},
updateTagsSubMenu: function(tagList) {
const contextTagList = $('contextTagList');
while (contextTagList.firstChild !== null)
contextTagList.removeChild(contextTagList.firstChild);
contextTagList.appendChild(new Element('li', {
html: '<a href="javascript:torrentAddTagsFN();">'
+ '<img src="images/qbt-theme/list-add.svg" alt="QBT_TR(Add...)QBT_TR[CONTEXT=TransferListWidget]"/>'
+ ' QBT_TR(Add...)QBT_TR[CONTEXT=TransferListWidget]'
+ '</a>'
}));
contextTagList.appendChild(new Element('li', {
html: '<a href="javascript:torrentRemoveAllTagsFN();">'
+ '<img src="images/qbt-theme/edit-clear.svg" alt="QBT_TR(Remove All)QBT_TR[CONTEXT=TransferListWidget]"/>'
+ ' QBT_TR(Remove All)QBT_TR[CONTEXT=TransferListWidget]'
+ '</a>'
}));
const sortedTags = [];
for (const key in tagList)
sortedTags.push(tagList[key].name);
sortedTags.sort();
for (let i = 0; i < sortedTags.length; ++i) {
const tagName = sortedTags[i];
const tagHash = genHash(tagName);
const el = new Element('li', {
html: '<a href="#Tag/' + tagHash + '" onclick="event.preventDefault(); torrentSetTagsFN(\'' + tagHash + '\', !event.currentTarget.getElement(\'input[type=checkbox]\').checked);">'
+ '<input type="checkbox" onclick="this.checked = !this.checked;"> ' + window.qBittorrent.Misc.escapeHtml(tagName)
+ '</a>'
});
if (i === 0)
el.addClass('separator');
contextTagList.appendChild(el);
}
}
}
});
const CategoriesFilterContextMenu = new Class({
Extends: ContextMenu,
updateMenuItems: function() {
const id = this.options.element.id;
if ((id != CATEGORIES_ALL) && (id != CATEGORIES_UNCATEGORIZED)) {
this.showItem('editCategory');
this.showItem('deleteCategory');
});
const CategoriesFilterContextMenu = new Class({
Extends: ContextMenu,
updateMenuItems: function() {
const id = this.options.element.id;
if ((id != CATEGORIES_ALL) && (id != CATEGORIES_UNCATEGORIZED)) {
this.showItem('editCategory');
this.showItem('deleteCategory');
}
else {
this.hideItem('editCategory');
this.hideItem('deleteCategory');
}
}
else {
this.hideItem('editCategory');
this.hideItem('deleteCategory');
});
const TagsFilterContextMenu = new Class({
Extends: ContextMenu,
updateMenuItems: function() {
const id = this.options.element.id;
if ((id !== TAGS_ALL.toString()) && (id !== TAGS_UNTAGGED.toString()))
this.showItem('deleteTag');
else
this.hideItem('deleteTag');
}
}
});
const TagsFilterContextMenu = new Class({
Extends: ContextMenu,
updateMenuItems: function() {
const id = this.options.element.id;
if ((id !== TAGS_ALL.toString()) && (id !== TAGS_UNTAGGED.toString()))
this.showItem('deleteTag');
else
this.hideItem('deleteTag');
}
});
const SearchPluginsTableContextMenu = new Class({
Extends: ContextMenu,
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();
})();

175
src/webui/www/private/scripts/download.js

@ -23,98 +23,113 @@ @@ -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();
})();

3519
src/webui/www/private/scripts/dynamicTable.js

File diff suppressed because it is too large Load Diff

306
src/webui/www/private/scripts/file-tree.js

@ -28,149 +28,167 @@ @@ -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();
})();

69
src/webui/www/private/scripts/filesystem.js

@ -30,32 +30,49 @@ @@ -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();
})();

312
src/webui/www/private/scripts/misc.js

@ -28,166 +28,188 @@ @@ -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, "<a target='_blank' href='$1'>$1</a>");
}
/*
* JS counterpart of the function in src/misc.cpp
*/
const parseHtmlLinks = function(text) {
const exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
return text.replace(exp, "<a target='_blank' href='$1'>$1</a>");
}
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<String>} terms terms to search for within the text
* @returns {Boolean} true if all terms match the text, false otherwise
*/
const containsAllTerms = function(text, terms) {
const textToSearch = text.toLowerCase();
return terms.every((function(term) {
const isTermRequired = (term[0] === '+');
const isTermExcluded = (term[0] === '-');
if (isTermRequired || isTermExcluded) {
// ignore lonely +/-
if (term.length === 1)
return true;
term = term.substring(1);
}
/**
*
* @param {String} text the text to search
* @param {Array<String>} terms terms to search for within the text
* @returns {Boolean} true if all terms match the text, false otherwise
*/
function containsAllTerms(text, terms) {
const textToSearch = text.toLowerCase();
return terms.every((function(term) {
const isTermRequired = (term[0] === '+');
const isTermExcluded = (term[0] === '-');
if (isTermRequired || isTermExcluded) {
// ignore lonely +/-
if (term.length === 1)
return true;
term = term.substring(1);
}
const textContainsTerm = (textToSearch.indexOf(term) !== -1);
return isTermExcluded ? !textContainsTerm : textContainsTerm;
}));
}
const textContainsTerm = (textToSearch.indexOf(term) !== -1);
return isTermExcluded ? !textContainsTerm : textContainsTerm;
}));
}
return exports();
})();

2
src/webui/www/private/scripts/mocha-init.js

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

44
src/webui/www/private/scripts/preferences.js

@ -28,20 +28,34 @@ @@ -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();
})();

219
src/webui/www/private/scripts/progressbar.js

@ -28,113 +28,126 @@ @@ -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();
})();

1171
src/webui/www/private/scripts/prop-files.js

File diff suppressed because it is too large Load Diff

344
src/webui/www/private/scripts/prop-general.js

@ -28,172 +28,186 @@ @@ -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();
})();

266
src/webui/www/private/scripts/prop-peers.js

@ -28,144 +28,160 @@ @@ -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();
})();

372
src/webui/www/private/scripts/prop-trackers.js

@ -28,195 +28,211 @@ @@ -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();
})();

202
src/webui/www/private/scripts/prop-webseeds.js

@ -28,112 +28,126 @@ @@ -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();
})();

2
src/webui/www/private/setlocation.html

@ -33,7 +33,7 @@ @@ -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) {

4
src/webui/www/private/shareratio.html

@ -37,9 +37,9 @@ @@ -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])
};

4
src/webui/www/private/upload.html

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

34
src/webui/www/private/views/about.html

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

64
src/webui/www/private/views/aboutToolbar.html

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

145
src/webui/www/private/views/filters.html

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

82
src/webui/www/private/views/installsearchplugin.html

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

2027
src/webui/www/private/views/preferences.html

File diff suppressed because it is too large Load Diff

54
src/webui/www/private/views/preferencesToolbar.html

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

8
src/webui/www/private/views/properties.html

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

1007
src/webui/www/private/views/search.html

File diff suppressed because it is too large Load Diff

283
src/webui/www/private/views/searchplugins.html

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

150
src/webui/www/private/views/transferlist.html

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

Loading…
Cancel
Save