From c54271638bc4cb049029a67d4d6f3f4d5a4964b6 Mon Sep 17 00:00:00 2001 From: Gabriele Date: Mon, 8 Dec 2014 21:00:00 +0100 Subject: [PATCH] WebUI: Load properties tabs once Don't reload HTML on tab change. Load the entire structure once and keep the unused bits hidden. Keep also the JS code separately, one file per tab. NOTE: tabs content is not loaded. This will be fixed in the next commit. --- src/webui/webui.qrc | 7 +- src/webui/www/public/prop-files.html | 338 ----------------- src/webui/www/public/prop-general.html | 123 ------- src/webui/www/public/prop-trackers.html | 146 -------- src/webui/www/public/properties.html | 41 +-- src/webui/www/public/properties_content.html | 61 +++ src/webui/www/public/scripts/client.js | 26 +- src/webui/www/public/scripts/prop-files.js | 348 ++++++++++++++++++ src/webui/www/public/scripts/prop-general.js | 84 +++++ src/webui/www/public/scripts/prop-trackers.js | 127 +++++++ 10 files changed, 654 insertions(+), 647 deletions(-) delete mode 100644 src/webui/www/public/prop-files.html delete mode 100644 src/webui/www/public/prop-general.html delete mode 100644 src/webui/www/public/prop-trackers.html create mode 100644 src/webui/www/public/properties_content.html create mode 100644 src/webui/www/public/scripts/prop-files.js create mode 100644 src/webui/www/public/scripts/prop-general.js create mode 100644 src/webui/www/public/scripts/prop-trackers.js diff --git a/src/webui/webui.qrc b/src/webui/webui.qrc index f0b7a13b8..db5f1c413 100644 --- a/src/webui/webui.qrc +++ b/src/webui/webui.qrc @@ -30,9 +30,10 @@ www/public/preferences.html www/public/preferences_content.html www/public/properties.html - www/public/prop-files.html - www/public/prop-general.html - www/public/prop-trackers.html + www/public/properties_content.html + www/public/scripts/prop-general.js + www/public/scripts/prop-trackers.js + www/public/scripts/prop-files.js www/public/transferlist.html www/public/upload.html www/public/uploadlimit.html diff --git a/src/webui/www/public/prop-files.html b/src/webui/www/public/prop-files.html deleted file mode 100644 index a5ce18d9b..000000000 --- a/src/webui/www/public/prop-files.html +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - -
_(Name)_(Size)_(Progress)_(Priority)
-
- - diff --git a/src/webui/www/public/prop-general.html b/src/webui/www/public/prop-general.html deleted file mode 100644 index 029312dbe..000000000 --- a/src/webui/www/public/prop-general.html +++ /dev/null @@ -1,123 +0,0 @@ -
- _(Transfer) - - - - -
_(Uploaded:)0 Kb_(UP limit:)xx_(Share ratio:)xx
_(Downloaded:)0 Kb_(DL limit:)xx_(Connections:)xx
_(Wasted:)0 Kb_(Time active:)xx
-
- -
- _(Information) - - - - - - -
_(Save path:)xxx
_(Created on:)xxx
_(Pieces size:)xxx
_(Torrent hash:)xxx
-
- _(Comment:) -
- -
-
-
- - - - diff --git a/src/webui/www/public/prop-trackers.html b/src/webui/www/public/prop-trackers.html deleted file mode 100644 index bff7ae6e7..000000000 --- a/src/webui/www/public/prop-trackers.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - - - - - - - -
_(URL) _(Status)_(Peers)_(Message)
-
- - diff --git a/src/webui/www/public/properties.html b/src/webui/www/public/properties.html index 0aa80f3cd..ecf76776b 100644 --- a/src/webui/www/public/properties.html +++ b/src/webui/www/public/properties.html @@ -1,37 +1,8 @@ - -
- -
+ +
diff --git a/src/webui/www/public/properties_content.html b/src/webui/www/public/properties_content.html new file mode 100644 index 000000000..798b30671 --- /dev/null +++ b/src/webui/www/public/properties_content.html @@ -0,0 +1,61 @@ +
+
+ _(Transfer) + + + + +
_(Uploaded:)_(UP limit:)_(Share ratio:)
_(Downloaded:)_(DL limit:)_(Connections:)
_(Wasted:)_(Time active:)
+
+ +
+ _(Information) + + + + + + +
_(Save path:)
_(Created on:)
_(Pieces size:)
_(Torrent hash:)
+
+ _(Comment:) +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/src/webui/www/public/scripts/client.js b/src/webui/www/public/scripts/client.js index 67ab70e73..1dfa9425e 100644 --- a/src/webui/www/public/scripts/client.js +++ b/src/webui/www/public/scripts/client.js @@ -311,11 +311,33 @@ window.addEvent('load', function () { bottom : 0, left : 0 }, - contentURL : 'prop-general.html', + contentURL : 'properties_content.html', require : { - css : ['css/Tabs.css'] + css : ['css/Tabs.css'], + js : ['scripts/prop-general.js', 'scripts/prop-trackers.js', 'scripts/prop-files.js'], }, tabsURL : 'properties.html', + tabsOnload : function() { + MochaUI.initializeTabs('propertiesTabs'); + + $('PropGeneralLink').addEvent('click', function(e){ + $('prop_general').removeClass("invisible"); + $('prop_trackers').addClass("invisible"); + $('prop_files').addClass("invisible"); + }); + + $('PropTrackersLink').addEvent('click', function(e){ + $('prop_trackers').removeClass("invisible"); + $('prop_general').addClass("invisible"); + $('prop_files').addClass("invisible"); + }); + + $('PropFilesLink').addEvent('click', function(e){ + $('prop_files').removeClass("invisible"); + $('prop_general').addClass("invisible"); + $('prop_trackers').addClass("invisible"); + }); + }, column : 'mainColumn', height : prop_h }); diff --git a/src/webui/www/public/scripts/prop-files.js b/src/webui/www/public/scripts/prop-files.js new file mode 100644 index 000000000..de326d675 --- /dev/null +++ b/src/webui/www/public/scripts/prop-files.js @@ -0,0 +1,348 @@ +var waitingTorrentFiles = false; +var is_seed = true; +var current_hash = ""; + +if (!(Browser.name == "ie" && Browser.version < 9)) { + $("all_files_cb").removeClass("tristate"); + $("all_files_cb").removeClass("partial"); + $("all_files_cb").removeClass("checked"); + $("tristate_cb").style.display = "inline"; +} + +var setCBState = function(state) { + if (Browser.name == "ie" && Browser.version < 9) { + if (state == "partial") { + if (!$("all_files_cb").hasClass("partial")) { + $("all_files_cb").removeClass("checked"); + $("all_files_cb").addClass("partial"); + } + return; + } + if (state == "checked") { + if (!$("all_files_cb").hasClass("checked")) { + $("all_files_cb").removeClass("partial"); + $("all_files_cb").addClass("checked"); + } + return; + } + $("all_files_cb").removeClass("partial"); + $("all_files_cb").removeClass("checked"); + } + else { + if (state == "partial") { + $("tristate_cb").indeterminate = true; + } + else if (state == "checked") { + $("tristate_cb").indeterminate = false; + $("tristate_cb").checked = true; + } + else { + $("tristate_cb").indeterminate = false; + $("tristate_cb").checked = false; + } + } +} + +var switchCBState = function() { + // Uncheck + if ($("all_files_cb").hasClass("partial")) { + $("all_files_cb").removeClass("partial"); + // Uncheck all checkboxes + $$('input.DownloadedCB').each(function(item, index) { + item.erase("checked"); + setFilePriority(index, 0); + }); + return; + } + if ($("all_files_cb").hasClass("checked")) { + $("all_files_cb").removeClass("checked"); + // Uncheck all checkboxes + $$('input.DownloadedCB').each(function(item, index) { + item.erase("checked"); + setFilePriority(index, 0); + }); + return; + } + // Check + $("all_files_cb").addClass("checked"); + // Check all checkboxes + $$('input.DownloadedCB').each(function(item, index) { + item.set("checked", "checked"); + setFilePriority(index, 1); + }); +} + +var allCBChecked = function() { + var CBs = $$('input.DownloadedCB'); + for (var i = 0; i < CBs.length; i += 1) { + var item = CBs[i]; + if (!$defined(item.get('checked')) || !item.get('checked')) + return false; + } + return true; +} + +var allCBUnchecked = function() { + var CBs = $$('input.DownloadedCB'); + for (var i = 0; i < CBs.length; i += 1) { + var item = CBs[i]; + if ($defined(item.get('checked')) && item.get('checked')) + return false; + } + return true; +} + +var setFilePriority = function(id, priority) { + if (current_hash == "") return; + new Request({ + url: 'command/setFilePrio', + method: 'post', + data: { + 'hash': current_hash, + 'id': id, + 'priority': priority + } + }).send(); + // Display or add combobox + if (priority > 0) { + $('comboPrio' + id).set("value", 1); + $('comboPrio' + id).removeClass("invisible"); + } + else { + $('comboPrio' + id).addClass("invisible"); + } +} + +var createDownloadedCB = function(id, downloaded) { + var CB = new Element('input'); + CB.set('type', 'checkbox'); + if (downloaded) + CB.set('checked', 'checked'); + CB.set('id', 'cbPrio' + id); + CB.set('class', 'DownloadedCB'); + CB.addEvent('change', function(e) { + var checked = 0; + if ($defined($('cbPrio' + id).get('checked')) && $('cbPrio' + id).get('checked')) + checked = 1; + setFilePriority(id, checked); + if (allCBChecked()) { + setCBState("checked"); + } + else { + if (allCBUnchecked()) { + setCBState("unchecked"); + } + else { + setCBState("partial"); + } + } + }); + return CB; +} + +var createPriorityCombo = function(id, selected_prio) { + var select = new Element('select'); + select.set('id', 'comboPrio' + id); + select.addEvent('change', function(e) { + var new_prio = $('comboPrio' + id).get('value'); + setFilePriority(id, new_prio); + }); + var opt = new Element("option"); + opt.set('value', '1') + opt.set('html', "_(Normal)"); + if (selected_prio <= 1) + opt.setAttribute('selected', ''); + opt.injectInside(select); + opt = new Element("option"); + opt.set('value', '2') + opt.set('html', "_(High)"); + if (selected_prio == 2) + opt.setAttribute('selected', ''); + opt.injectInside(select); + opt = new Element("option"); + opt.set('value', '7') + opt.set('html', "_(Maximum)"); + if (selected_prio == 7) + opt.setAttribute('selected', ''); + opt.injectInside(select); + if (is_seed || selected_prio < 1) { + select.addClass("invisible"); + } + else { + select.removeClass("invisible"); + } + select.addClass("combo_priority"); + return select; +} + +var filesDynTable = new Class({ + + initialize: function() {}, + + setup: function(table) { + this.table = $(table); + this.rows = new Hash(); + }, + + removeRow: function(id) { + if (this.rows.has(id)) { + var tr = this.rows.get(id); + tr.dispose(); + this.rows.erase(id); + return true; + } + return false; + }, + + removeAllRows: function() { + this.rows.each(function(tr, id) { + this.removeRow(id); + }.bind(this)); + }, + + updateRow: function(tr, row, id) { + var tds = tr.getElements('td'); + for (var i = 0; i < row.length; i++) { + if (i == 3) { + $('pbf_' + id).setValue(row[i].toFloat()); + } + else { + if (i == 0) { + if (row[i] > 0) + tds[i].getChildren('input')[0].set('checked', 'checked'); + else + tds[i].getChildren('input')[0].removeProperty('checked') + } + else { + if (i == 4) { + if (!is_seed && row[i] > 0) { + tds[i].getChildren('select').set('value', row[i]); + $('comboPrio' + id).removeClass("invisible"); + } + else { + if (!$('comboPrio' + id).hasClass("invisible")) + $('comboPrio' + id).addClass("invisible"); + } + } + else { + tds[i].set('html', row[i]); + } + } + } + } + return true; + }, + + insertRow: function(id, row) { + if (this.rows.has(id)) { + var tr = this.rows.get(id); + this.updateRow(tr, row, id); + return; + } + //this.removeRow(id); + var tr = new Element('tr'); + this.rows.set(id, tr); + for (var i = 0; i < row.length; i++) { + var td = new Element('td'); + if (i == 3) { + td.adopt(new ProgressBar(row[i].toFloat(), { + 'id': 'pbf_' + id, + 'width': 80 + })); + } + else { + if (i == 0) { + var tree_img = new Element('img', { + src: 'images/L.gif', + style: 'margin-bottom: -2px' + }); + td.adopt(tree_img, createDownloadedCB(id, row[i])); + } + else { + if (i == 4) { + td.adopt(createPriorityCombo(id, row[i])); + } + else { + td.set('html', row[i]); + } + } + } + td.injectInside(tr); + } + tr.injectInside(this.table); + }, +}); + +var loadTorrentFilesData = function() { + if ($('prop_files').hasClass('invisible')) { + // Tab changed, don't do anything + return; + } + var new_hash = myTable.getCurrentTorrentHash(); + if (new_hash == "") { + fTable.removeAllRows(); + loadTorrentFilesData.delay(1500); + return; + } + if (new_hash != current_hash) { + fTable.removeAllRows(); + current_hash = new_hash; + } + var url = 'json/propertiesFiles/' + current_hash; + if (!waitingTorrentFiles) { + waitingTorrentFiles = true; + var request = new Request.JSON({ + url: url, + noCache: true, + method: 'get', + onFailure: function() { + $('error_div').set('html', '_(qBittorrent client is not reachable)'); + waitingTorrentFiles = false; + loadTorrentFilesData.delay(2000); + }, + onSuccess: function(files) { + $('error_div').set('html', ''); + if (files) { + // Update Trackers data + var i = 0; + files.each(function(file) { + if (i == 0) { + is_seed = file.is_seed; + } + var row = new Array(); + row.length = 4; + row[0] = file.priority; + row[1] = file.name; + row[2] = friendlyUnit(file.size, false); + row[3] = (file.progress * 100).round(1); + if (row[3] == 100.0 && file.progress < 1.0) + row[3] = 99.9 + row[4] = file.priority; + fTable.insertRow(i, row); + i++; + }.bind(this)); + // Set global CB state + if (allCBChecked()) { + setCBState("checked"); + } + else { + if (allCBUnchecked()) { + setCBState("unchecked"); + } + else { + setCBState("partial"); + } + } + } + else { + fTable.removeAllRows(); + } + waitingTorrentFiles = false; + loadTorrentFilesData.delay(1500); + } + }).send(); + } + +} +fTable = new filesDynTable(); +fTable.setup($('filesTable')); \ No newline at end of file diff --git a/src/webui/www/public/scripts/prop-general.js b/src/webui/www/public/scripts/prop-general.js new file mode 100644 index 000000000..5afe750d3 --- /dev/null +++ b/src/webui/www/public/scripts/prop-general.js @@ -0,0 +1,84 @@ +var waiting = false; + +var clearData = function() { + $('torrent_hash').set('html', ''); + $('save_path').set('html', ''); + $('creation_date').set('html', ''); + $('piece_size').set('html', ''); + $('comment').set('html', ''); + $('total_uploaded').set('html', ''); + $('total_downloaded').set('html', ''); + $('total_wasted').set('html', ''); + $('up_limit').set('html', ''); + $('dl_limit').set('html', ''); + $('time_elapsed').set('html', ''); + $('nb_connections').set('html', ''); + $('share_ratio').set('html', ''); +} + +var loadData = function() { + if ($('prop_general').hasClass('invisible')) { + // Tab changed, don't do anything + return; + } + var current_hash = myTable.getCurrentTorrentHash(); + if (current_hash == "") { + clearData(); + loadData.delay(1500); + return; + } + // Display hash + $('torrent_hash').set('html', current_hash); + var url = 'json/propertiesGeneral/' + current_hash; + if (!waiting) { + waiting = true; + var request = new Request.JSON({ + url: url, + noCache: true, + method: 'get', + onFailure: function() { + $('error_div').set('html', '_(qBittorrent client is not reachable)'); + waiting = false; + loadData.delay(2000); + }, + onSuccess: function(data) { + $('error_div').set('html', ''); + if (data) { + var temp; + // Update Torrent data + $('save_path').set('html', data.save_path); + temp = data.creation_date; + var timestamp = "_(Unknown)"; + if (temp != -1) + timestamp = new Date(data.creation_date * 1000).toISOString(); + $('creation_date').set('html', timestamp); + $('piece_size').set('html', friendlyUnit(data.piece_size)); + $('comment').set('html', data.comment); + $('total_uploaded').set('html', friendlyUnit(data.total_uploaded) + + " (" + friendlyUnit(data.total_uploaded_session) + + " (" + "_(this session)" + ")"); + $('total_downloaded').set('html', friendlyUnit(data.total_downloaded) + + " (" + friendlyUnit(data.total_downloaded_session) + + " (" + "_(this session)" + ")"); + $('total_wasted').set('html', data.total_wasted); + temp = data.up_limit; + $('up_limit').set('html', temp == -1 ? "∞" : temp); + temp = data.dl_limit; + $('dl_limit').set('html', temp == -1 ? "∞" : temp); + temp = friendlyDuration(status.active_time); + if (status.is_seed) + temp += " (" + "_(Seeded for %1)".replace("%1", status.seeding_time) + ")"; + $('time_elapsed').set('html', temp); + temp = data.nb_connections + " (" + "_(%1 max)".replace("%1", status.nb_connections_limit) + ")"; + $('nb_connections').set('html', temp); + $('share_ratio').set('html', data.share_ratio.toFixed(2)); + } + else { + clearData(); + } + waiting = false; + loadData.delay(1500); + } + }).send(); + } +} \ No newline at end of file diff --git a/src/webui/www/public/scripts/prop-trackers.js b/src/webui/www/public/scripts/prop-trackers.js new file mode 100644 index 000000000..8fbd1fe04 --- /dev/null +++ b/src/webui/www/public/scripts/prop-trackers.js @@ -0,0 +1,127 @@ +var trackersDynTable = new Class({ + + initialize: function() {}, + + setup: function(table) { + this.table = $(table); + this.rows = new Hash(); + }, + + removeRow: function(url) { + if (this.rows.has(url)) { + var tr = this.rows.get(url); + tr.dispose(); + this.rows.erase(url); + return true; + } + return false; + }, + + removeAllRows: function() { + this.rows.each(function(tr, url) { + this.removeRow(url); + }.bind(this)); + }, + + updateRow: function(tr, row) { + var tds = tr.getElements('td'); + for (var i = 0; i < row.length; i++) { + tds[i].set('html', row[i]); + } + return true; + }, + + insertRow: function(row) { + var url = row[0]; + if (this.rows.has(url)) { + var tr = this.rows.get(url); + this.updateRow(tr, row); + return; + } + //this.removeRow(id); + var tr = new Element('tr'); + this.rows.set(url, tr); + for (var i = 0; i < row.length; i++) { + var td = new Element('td'); + td.set('html', row[i]); + td.injectInside(tr); + } + tr.injectInside(this.table); + }, +}); + +var waitingTrackers = false; +var current_hash = ""; + +var loadTrackersData = function() { + if ($('prop_trackers').hasClass('invisible')) { + // Tab changed, don't do anything + return; + } + var new_hash = myTable.getCurrentTorrentHash(); + if (new_hash == "") { + tTable.removeAllRows(); + loadTrackersData.delay(1500); + return; + } + if (new_hash != current_hash) { + tTable.removeAllRows(); + current_hash = new_hash; + } + var url = 'json/propertiesTrackers/' + current_hash; + if (!waitingTrackers) { + waitingTrackers = true; + var request = new Request.JSON({ + url: url, + noCache: true, + method: 'get', + onFailure: function() { + $('error_div').set('html', '_(qBittorrent client is not reachable)'); + waitingTrackers = false; + loadTrackersData.delay(2000); + }, + onSuccess: function(trackers) { + $('error_div').set('html', ''); + if (trackers) { + // Update Trackers data + trackers.each(function(tracker) { + var row = new Array(); + row.length = 4; + row[0] = tracker.url; + row[1] = tracker.status; + row[2] = tracker.num_peers; + row[3] = tracker.msg; + tTable.insertRow(row); + }); + } + else { + tTable.removeAllRows(); + } + waitingTrackers = false; + loadTrackersData.delay(1500); + } + }).send(); + } + +} +tTable = new trackersDynTable(); +tTable.setup($('trackersTable')); + +// Add trackers code +$('addTrackersPlus').addEvent('click', function addTrackerDlg() { + if (current_hash.length == 0) return; + new MochaUI.Window({ + id: 'trackersPage', + title: "_(Trackers addition dialog)", + loadMethod: 'iframe', + contentURL: 'addtrackers.html?hash=' + current_hash, + scrollbars: true, + resizable: false, + maximizable: false, + closable: true, + paddingVertical: 0, + paddingHorizontal: 0, + width: 500, + height: 250 + }); +}); \ No newline at end of file