2030 lines
68 KiB
JavaScript
2030 lines
68 KiB
JavaScript
/*
|
|
* overdrive.js
|
|
* Copyright (C) 2016 L. Bradley LaBoon <me@bradleylaboon.com>
|
|
*
|
|
* This file is part of Overdrive.
|
|
*
|
|
* Overdrive is free software: you can redistribute it and/or modify it under
|
|
* the terms terms of the GNU General Public License as published by the Free
|
|
* Software Foundation, either verion 3 of the License, or (at your option) any
|
|
* later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/* Global Namespace */
|
|
var _overdrive = {};
|
|
|
|
/* Settings */
|
|
_overdrive.settings = {};
|
|
_overdrive.settings.binaryKB = true;
|
|
_overdrive.settings.columns = [
|
|
"id",
|
|
"name",
|
|
"totalSize",
|
|
"status",
|
|
"percentDone",
|
|
"rateDownload",
|
|
"rateUpload",
|
|
"eta",
|
|
"uploadRatio"
|
|
];
|
|
_overdrive.settings.rpcURL = "/transmission/rpc";
|
|
_overdrive.settings.refreshRate = 1000;
|
|
// This will be initialized after the first request to the server
|
|
_overdrive.settings.sessionID = "";
|
|
|
|
/* Data Objects */
|
|
_overdrive.data = {};
|
|
_overdrive.data.columnNames = {};
|
|
_overdrive.data.selected = [];
|
|
_overdrive.data.torrents = {};
|
|
_overdrive.data.torrentsDetail = {};
|
|
_overdrive.data.torrentStat = {};
|
|
_overdrive.data.session = {};
|
|
|
|
/* Torrent Status (values given by Transmission RPC) */
|
|
_overdrive.data.torrentStat.stopped = 0;
|
|
_overdrive.data.torrentStat.checkWait = 1;
|
|
_overdrive.data.torrentStat.check = 2;
|
|
_overdrive.data.torrentStat.downloadWait = 3;
|
|
_overdrive.data.torrentStat.download = 4;
|
|
_overdrive.data.torrentStat.seedWait = 5;
|
|
_overdrive.data.torrentStat.seed = 6;
|
|
_overdrive.data.torrentStatStrings = [
|
|
"Paused",
|
|
"Waiting (C)",
|
|
"Checking",
|
|
"Waiting (D)",
|
|
"Downloading",
|
|
"Waiting (S)",
|
|
"Seeding"
|
|
];
|
|
|
|
/* Torrent Column Names */
|
|
_overdrive.data.columnNames.activityDate = "Activity Date";
|
|
_overdrive.data.columnNames.addedDate = "Added Date";
|
|
_overdrive.data.columnNames.bandwidthPriority = "Priority";
|
|
_overdrive.data.columnNames.comment = "Comment";
|
|
_overdrive.data.columnNames.corruptEver = "Corrupt";
|
|
_overdrive.data.columnNames.creator = "Creator";
|
|
_overdrive.data.columnNames.dateCreated = "Date Created";
|
|
_overdrive.data.columnNames.desiredAvailable = "Desired Available";
|
|
_overdrive.data.columnNames.doneDate = "Finished Date";
|
|
_overdrive.data.columnNames.downloadDir = "Directory";
|
|
_overdrive.data.columnNames.downloadedEver = "Downloaded Ever";
|
|
_overdrive.data.columnNames.downloadLimit = "Down Limit";
|
|
_overdrive.data.columnNames.downloadLimited = "Down Limited";
|
|
_overdrive.data.columnNames.error = "Error";
|
|
_overdrive.data.columnNames.errorString = "Error String";
|
|
_overdrive.data.columnNames.eta = "ETA";
|
|
_overdrive.data.columnNames.etaIdle = "ETA Idle";
|
|
_overdrive.data.columnNames.hashString = "Hash";
|
|
_overdrive.data.columnNames.haveUnchecked = "Unchecked";
|
|
_overdrive.data.columnNames.haveValid = "Downloaded";
|
|
_overdrive.data.columnNames.honorsSessionLimits = "Honors Session Limits";
|
|
_overdrive.data.columnNames.id = "#";
|
|
_overdrive.data.columnNames.isFinished = "Finished";
|
|
_overdrive.data.columnNames.isPrivate = "Private";
|
|
_overdrive.data.columnNames.isStalled = "Stalled";
|
|
_overdrive.data.columnNames.leftUntilDone = "Remaining";
|
|
_overdrive.data.columnNames.magnetLink = "Magnet Link";
|
|
_overdrive.data.columnNames.manualAnnounceTime = "Time Until Manual Announce";
|
|
_overdrive.data.columnNames.maxConnectedPeers = "Max Connected Peers";
|
|
_overdrive.data.columnNames.metadataPercentComplete = "Metadata Progress";
|
|
_overdrive.data.columnNames.name = "Name";
|
|
_overdrive.data.columnNames["peer-limit"] = "Peer Limit";
|
|
_overdrive.data.columnNames.peersConnected = "Peers";
|
|
_overdrive.data.columnNames.peersGettingFromUs = "Peers Taking";
|
|
_overdrive.data.columnNames.peersSendingToUs = "Peers Giving";
|
|
_overdrive.data.columnNames.percentDone = "Progress";
|
|
_overdrive.data.columnNames.pieceCount = "Pieces";
|
|
_overdrive.data.columnNames.pieceSize = "Piece Size";
|
|
_overdrive.data.columnNames.queuePosition = "Position";
|
|
_overdrive.data.columnNames.rateDownload = "Down Speed";
|
|
_overdrive.data.columnNames.rateUpload = "Up Speed";
|
|
_overdrive.data.columnNames.recheckProgress = "Recheck Progress";
|
|
_overdrive.data.columnNames.secondsDownloading = "Time Downloading";
|
|
_overdrive.data.columnNames.secondsSeeding = "Time Seeding";
|
|
_overdrive.data.columnNames.seedIdleLimit = "Seed Idle Limit";
|
|
_overdrive.data.columnNames.seedIdleMode = "Seed Idle Mode";
|
|
_overdrive.data.columnNames.seedRatioLimit = "Seed Ratio Limit";
|
|
_overdrive.data.columnNames.seedRatioMode = "Seed Ratio Mode";
|
|
_overdrive.data.columnNames.sizeWhenDone = "Wanted Size";
|
|
_overdrive.data.columnNames.startDate = "Start Date";
|
|
_overdrive.data.columnNames.status = "Status";
|
|
_overdrive.data.columnNames.totalSize = "Size";
|
|
_overdrive.data.columnNames.torrentFile = "Torrent File";
|
|
_overdrive.data.columnNames.uploadedEver = "Uploaded";
|
|
_overdrive.data.columnNames.uploadLimit = "Up Limit";
|
|
_overdrive.data.columnNames.uploadRatio = "Ratio";
|
|
_overdrive.data.columnNames.webseedsSendingToUs = "Web Seeds";
|
|
|
|
// List of columns that contain string data
|
|
_overdrive.data.stringCols = [
|
|
"comment",
|
|
"creator",
|
|
"downloadDir",
|
|
"errorString",
|
|
"hashString",
|
|
"name",
|
|
"torrentFile"
|
|
];
|
|
|
|
/* Last sent/received tags */
|
|
_overdrive.data.lastSent = 0;
|
|
_overdrive.data.lastReceived = -1;
|
|
_overdrive.data.lastSentSession = 0;
|
|
_overdrive.data.lastReceivedSession = -1;
|
|
_overdrive.data.lastSentDetail = 0;
|
|
_overdrive.data.lastReceivedDetail = -1;
|
|
|
|
/* UI Object */
|
|
_overdrive.ui = {};
|
|
|
|
/* Button variables */
|
|
_overdrive.ui.pauseEnabled = false;
|
|
_overdrive.ui.pauseImg = "img/pause.png";
|
|
_overdrive.ui.pauseImgDisabled = "img/pause-disabled.png";
|
|
_overdrive.ui.resumeEnabled = false;
|
|
_overdrive.ui.resumeImg = "img/resume.png";
|
|
_overdrive.ui.resumeImgDisabled = "img/resume-disabled.png";
|
|
_overdrive.ui.deleteEnabled = false;
|
|
_overdrive.ui.deleteImg = "img/delete.png";
|
|
_overdrive.ui.deleteImgDisabled = "img/delete-disabled.png";
|
|
_overdrive.ui.altImg = "img/alt.png";
|
|
_overdrive.ui.altImgDisabled = "img/alt-disabled.png";
|
|
|
|
_overdrive.ui.displayState = [
|
|
_overdrive.data.torrentStat.stopped,
|
|
_overdrive.data.torrentStat.checkWait,
|
|
_overdrive.data.torrentStat.check,
|
|
_overdrive.data.torrentStat.downloadWait,
|
|
_overdrive.data.torrentStat.download,
|
|
_overdrive.data.torrentStat.seedWait,
|
|
_overdrive.data.torrentStat.seed
|
|
];
|
|
_overdrive.ui.sortCol = "name";
|
|
_overdrive.ui.sortAsc = true;
|
|
_overdrive.ui.fileSortCol = "name";
|
|
_overdrive.ui.fileSortAsc = true;
|
|
_overdrive.ui.peerSortCol = "address";
|
|
_overdrive.ui.peerSortAsc = true;
|
|
|
|
/* UI Variables (these will be initialized later) */
|
|
_overdrive.ui.listScrollX = 0;
|
|
_overdrive.ui.listScrollY = 0;
|
|
_overdrive.ui.fileListScrollX = 0;
|
|
_overdrive.ui.fileListScrollY = 0;
|
|
_overdrive.ui.peerListScrollX = 0;
|
|
_overdrive.ui.peerListScrollY = 0;
|
|
_overdrive.ui.statusTablePos = 0;
|
|
_overdrive.ui.sideLastX = 0;
|
|
_overdrive.ui.sideLastY = 0;
|
|
_overdrive.ui.sideResize = false;
|
|
_overdrive.ui.vertResize = false;
|
|
_overdrive.ui.windowDrag = false;
|
|
_overdrive.ui.activeWindow = null;
|
|
_overdrive.ui.lastClickedTorrent = -1;
|
|
_overdrive.ui.lastWidth = 0;
|
|
_overdrive.ui.lastHeight = 0;
|
|
_overdrive.ui.detailsPadding = 0;
|
|
_overdrive.ui.detailsMargin = 0;
|
|
_overdrive.ui.listMargin = 0;
|
|
_overdrive.ui.listBorder = 0;
|
|
_overdrive.ui.canvasColor = "";
|
|
_overdrive.ui.fontColor = "";
|
|
_overdrive.ui.fontSize = "";
|
|
_overdrive.ui.fontFamily = "";
|
|
_overdrive.ui.tableCellPadding = 0;
|
|
|
|
// Formats data within the torrents object
|
|
_overdrive.data.formatData = function(detail)
|
|
{
|
|
var torrents;
|
|
if (detail)
|
|
torrents = _overdrive.data.torrentsDetail;
|
|
else
|
|
torrents = _overdrive.data.torrents;
|
|
|
|
for (var i = 0; i < torrents.length; i++) {
|
|
// Initial data modification
|
|
if (torrents[i].status == _overdrive.data.torrentStat.seed && torrents[i].rateUpload <= 0)
|
|
torrents[i].status = _overdrive.data.torrentStat.seedWait;
|
|
|
|
if (_overdrive.settings.columns.indexOf("eta") != -1) {
|
|
if (torrents[i].eta < 0 && torrents[i].percentDone < 1)
|
|
torrents[i].eta = Number.MAX_VALUE;
|
|
}
|
|
|
|
// Formatting
|
|
for (var prop in torrents[i]) {
|
|
if (prop == "percentDone")
|
|
torrents[i].percentDoneHTML = (torrents[i].percentDone * 100).toFixed(2) + "%";
|
|
else if (prop == "totalSize")
|
|
torrents[i].totalSizeHTML = _overdrive.data.friendlyByteString(torrents[i].totalSize);
|
|
else if (prop == "rateDownload")
|
|
torrents[i].rateDownloadHTML = _overdrive.data.friendlyByteString(torrents[i].rateDownload) + "/s";
|
|
else if (prop == "rateUpload")
|
|
torrents[i].rateUploadHTML = _overdrive.data.friendlyByteString(torrents[i].rateUpload) + "/s";
|
|
else if (prop == "status")
|
|
torrents[i].statusHTML = _overdrive.data.torrentStatStrings[torrents[i].status];
|
|
else if (prop == "eta")
|
|
torrents[i].etaHTML = _overdrive.data.friendlyTimeString(torrents[i].eta);
|
|
else if (prop == "uploadRatio")
|
|
torrents[i].uploadRatioHTML = torrents[i].uploadRatio.toFixed(4);
|
|
else
|
|
torrents[i][prop + "HTML"] = torrents[i][prop];
|
|
}
|
|
}
|
|
};
|
|
|
|
// Convert number of bytes to a byte string
|
|
_overdrive.data.friendlyByteString = function(num)
|
|
{
|
|
var units = "";
|
|
var kbSize;
|
|
if (_overdrive.settings.binaryKB)
|
|
kbSize = 1024;
|
|
else
|
|
kbSize = 1000;
|
|
|
|
if (num >= kbSize) {
|
|
num /= kbSize;
|
|
units = "K";
|
|
}
|
|
if (num >= kbSize) {
|
|
num /= kbSize;
|
|
units = "M";
|
|
}
|
|
if (num >= kbSize) {
|
|
num /= kbSize;
|
|
units = "G";
|
|
}
|
|
if (num >= kbSize) {
|
|
num /= kbSize;
|
|
units = "T";
|
|
}
|
|
if (num >= kbSize) {
|
|
num /= kbSize;
|
|
units = "P";
|
|
}
|
|
if (num >= kbSize) {
|
|
num /= kbSize;
|
|
units = "E";
|
|
}
|
|
if (num >= kbSize) {
|
|
num /= kbSize;
|
|
units = "Z";
|
|
}
|
|
if (num >= kbSize) {
|
|
num /= kbSize;
|
|
units = "Y";
|
|
}
|
|
|
|
if (_overdrive.settings.binaryKB && units != "")
|
|
units += "i";
|
|
|
|
units += "B";
|
|
return num.toFixed(2) + " " + units;
|
|
};
|
|
|
|
// Convert number of seconds to a time string
|
|
_overdrive.data.friendlyTimeString = function(num)
|
|
{
|
|
num = num.toFixed(0);
|
|
if (num < 0) {
|
|
return "N/A";
|
|
} else if (num == Number.MAX_VALUE) {
|
|
return "Unknown";
|
|
} else {
|
|
var hours = 0, mins = 0;
|
|
|
|
while (num >= 3600) {
|
|
num -= 3600;
|
|
hours++;
|
|
}
|
|
|
|
while (num >= 60) {
|
|
num -= 60;
|
|
mins++;
|
|
}
|
|
|
|
if (hours < 10)
|
|
hours = "0" + hours;
|
|
if (mins < 10)
|
|
mins = "0" + mins;
|
|
if (num < 10)
|
|
num = "0" + num;
|
|
return hours + ":" + mins + ":" + num;
|
|
}
|
|
};
|
|
|
|
// Convert a string in Base64 encoding to a bit string
|
|
_overdrive.data.base64ToBits = function(str)
|
|
{
|
|
var base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
var bitString = "";
|
|
var pos = 0;
|
|
|
|
while (pos < str.length) {
|
|
var chunk = str.substr(pos, 4);
|
|
var count;
|
|
switch (chunk.lastIndexOf('=')) {
|
|
case 3:
|
|
count = 16;
|
|
break;
|
|
case 2:
|
|
count = 8;
|
|
break;
|
|
default:
|
|
count = 24;
|
|
}
|
|
|
|
for (var i = 0; i < 4; i++) {
|
|
if (chunk.charAt(i) != '=') {
|
|
var val = base64.indexOf(chunk.charAt(i));
|
|
var div = 32;
|
|
while (div >= 1) {
|
|
if (val >= div) {
|
|
bitString += "1";
|
|
val -= div;
|
|
} else {
|
|
bitString += "0";
|
|
}
|
|
|
|
if (count-- == 1)
|
|
break;
|
|
|
|
div /= 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
pos += 4;
|
|
}
|
|
|
|
return bitString;
|
|
};
|
|
|
|
// Get detailed torrent information from server about selected torrents
|
|
_overdrive.data.getDetailedInfo = function()
|
|
{
|
|
if (_overdrive.data.selected.length > 0) {
|
|
var request = {};
|
|
request.method = "torrent-get";
|
|
request.arguments = {};
|
|
request.arguments.ids = _overdrive.data.selected;
|
|
request.arguments.fields = [
|
|
"activityDate",
|
|
"addedDate",
|
|
"bandwidthPriority",
|
|
"comment",
|
|
"corruptEver",
|
|
"creator",
|
|
"dateCreated",
|
|
"desiredAvailable",
|
|
"doneDate",
|
|
"downloadDir",
|
|
"downloadedEver",
|
|
"downloadLimit",
|
|
"downloadLimited",
|
|
"error",
|
|
"errorString",
|
|
"eta",
|
|
"etaIdle",
|
|
"files",
|
|
"fileStats",
|
|
"hashString",
|
|
"haveUnchecked",
|
|
"haveValid",
|
|
"honorSessionLimits",
|
|
"id",
|
|
"isFinished",
|
|
"isPrivate",
|
|
"isStalled",
|
|
"leftUntilDone",
|
|
"magnetLink",
|
|
"manualAnnounceTime",
|
|
"maxConnectedPeers",
|
|
"metadataPercentComplete",
|
|
"name",
|
|
"peer-limit",
|
|
"peers",
|
|
"peersConnected",
|
|
"peersFrom",
|
|
"peersGettingFromUs",
|
|
"peersSendingToUs",
|
|
"percentDone",
|
|
"pieces",
|
|
"pieceCount",
|
|
"pieceSize",
|
|
"priorities",
|
|
"queuePosition",
|
|
"rateDownload",
|
|
"rateUpload",
|
|
"recheckProgress",
|
|
"secondsDownloading",
|
|
"secondsSeeding",
|
|
"seedIdleLimit",
|
|
"seedIdleMode",
|
|
"seedRatioLimit",
|
|
"seedRatioMode",
|
|
"sizeWhenDone",
|
|
"startDate",
|
|
"status",
|
|
"trackers",
|
|
"trackerStats",
|
|
"totalSize",
|
|
"torrentFile",
|
|
"uploadedEver",
|
|
"uploadLimit",
|
|
"uploadLimited",
|
|
"uploadRatio",
|
|
"wanted",
|
|
"webseeds",
|
|
"webseedsSendingToUs"
|
|
];
|
|
request.tag = _overdrive.data.lastSentDetail++;
|
|
|
|
var xmlhttp;
|
|
if (window.XMLHttpRequest)
|
|
xmlhttp = new XMLHttpRequest();
|
|
else
|
|
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
|
|
|
xmlhttp.open("POST", _overdrive.settings.rpcURL, true);
|
|
xmlhttp.setRequestHeader("X-Transmission-Session-Id", _overdrive.settings.sessionID);
|
|
var postData = JSON.stringify(request);
|
|
xmlhttp.setRequestHeader("Content-type", "application/json");
|
|
xmlhttp.send(postData);
|
|
|
|
xmlhttp.onreadystatechange = function()
|
|
{
|
|
if (xmlhttp.readyState == 4) {
|
|
if (xmlhttp.status == 409) {
|
|
_overdrive.settings.sessionID = xmlhttp.getResponseHeader("X-Transmission-Session-Id");
|
|
_overdrive.data.getDetailedInfo();
|
|
} else if (xmlhttp.status == 200) {
|
|
var response = JSON.parse(xmlhttp.responseText);
|
|
if (response.result != "success") {
|
|
alert("getDetailedInfo() failed: " + response.result);
|
|
} else {
|
|
if (response.tag > _overdrive.data.lastReceivedDetail) {
|
|
_overdrive.data.lastReceivedDetail = response.tag;
|
|
_overdrive.data.torrentsDetail = response.arguments.torrents;
|
|
_overdrive.data.formatData(true);
|
|
_overdrive.ui.refreshDetails();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
} else {
|
|
_overdrive.data.torrentsDetail = [];
|
|
_overdrive.ui.refreshDetails();
|
|
}
|
|
};
|
|
|
|
// Get everything from server
|
|
_overdrive.data.getEverything = function()
|
|
{
|
|
_overdrive.data.getTorrentInfo();
|
|
_overdrive.data.getSessionInfo();
|
|
_overdrive.data.getDetailedInfo();
|
|
};
|
|
|
|
// Get session information from server
|
|
_overdrive.data.getSessionInfo = function()
|
|
{
|
|
var request = {};
|
|
request.method = "session-get";
|
|
request.tag = _overdrive.data.lastSentSession++;
|
|
|
|
var xmlhttp;
|
|
if (window.XMLHttpRequest)
|
|
xmlhttp = new XMLHttpRequest();
|
|
else
|
|
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
|
|
|
xmlhttp.open("POST", _overdrive.settings.rpcURL, true);
|
|
xmlhttp.setRequestHeader("X-Transmission-Session-Id", _overdrive.settings.sessionID);
|
|
var postData = JSON.stringify(request);
|
|
xmlhttp.setRequestHeader("Content-type", "application/json");
|
|
xmlhttp.send(postData);
|
|
|
|
xmlhttp.onreadystatechange = function()
|
|
{
|
|
if (xmlhttp.readyState == 4) {
|
|
if (xmlhttp.status == 409) {
|
|
_overdrive.settings.sessionID = xmlhttp.getResponseHeader("X-Transmission-Session-Id");
|
|
_overdrive.data.getSessionInfo();
|
|
} else if (xmlhttp.status == 200) {
|
|
var response = JSON.parse(xmlhttp.responseText);
|
|
if (response.result != "success") {
|
|
alert("getSessionInfo() failed: " + response.result);
|
|
} else {
|
|
if (response.tag > _overdrive.data.lastReceivedSession) {
|
|
_overdrive.data.lastReceivedSession = response.tag;
|
|
_overdrive.data.session = response.arguments;
|
|
_overdrive.ui.refreshSettings();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
// Return the torrent with the specified id
|
|
_overdrive.data.getTorrentById = function(id)
|
|
{
|
|
for (var i = 0; i < _overdrive.data.torrents.length; i++) {
|
|
if (_overdrive.data.torrents[i].id == id)
|
|
return _overdrive.data.torrents[i];
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
// Get torrent information from server
|
|
_overdrive.data.getTorrentInfo = function()
|
|
{
|
|
var request = {};
|
|
request.method = "torrent-get";
|
|
request.arguments = {};
|
|
request.arguments.fields = _overdrive.settings.columns.concat();
|
|
if (request.arguments.fields.indexOf("id") == -1)
|
|
request.arguments.fields.push("id");
|
|
if (request.arguments.fields.indexOf("status") == -1)
|
|
request.arguments.fields.push("status");
|
|
if (request.arguments.fields.indexOf("percentDone") == -1)
|
|
request.arguments.fields.push("percentDone");
|
|
request.tag = _overdrive.data.lastSent++;
|
|
|
|
var xmlhttp;
|
|
if (window.XMLHttpRequest)
|
|
xmlhttp = new XMLHttpRequest();
|
|
else
|
|
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
|
|
|
xmlhttp.open("POST", _overdrive.settings.rpcURL, true);
|
|
xmlhttp.setRequestHeader("X-Transmission-Session-Id", _overdrive.settings.sessionID);
|
|
var postData = JSON.stringify(request);
|
|
xmlhttp.setRequestHeader("Content-type", "application/json");
|
|
xmlhttp.send(postData);
|
|
|
|
xmlhttp.onreadystatechange = function()
|
|
{
|
|
if (xmlhttp.readyState == 4) {
|
|
if (xmlhttp.status == 409) {
|
|
_overdrive.settings.sessionID = xmlhttp.getResponseHeader("X-Transmission-Session-Id");
|
|
_overdrive.data.getTorrentInfo();
|
|
} else if (xmlhttp.status == 200) {
|
|
var response = JSON.parse(xmlhttp.responseText);
|
|
if (response.result != "success") {
|
|
alert("getTorrentInfo() failed: " + response.result);
|
|
} else {
|
|
if (response.tag > _overdrive.data.lastReceived) {
|
|
_overdrive.data.lastReceived = response.tag;
|
|
_overdrive.data.validateSelection(response.arguments.torrents);
|
|
_overdrive.data.torrents = response.arguments.torrents;
|
|
_overdrive.data.formatData(false);
|
|
_overdrive.data.sortData();
|
|
_overdrive.ui.refreshControls();
|
|
_overdrive.ui.refreshList();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
// Get the index in the torrent array of the torrent with specified ID
|
|
_overdrive.data.indexOfID = function(id)
|
|
{
|
|
for (var i = 0; i < _overdrive.data.torrents.length; i++) {
|
|
if (_overdrive.data.torrents[i].id == id)
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
};
|
|
|
|
// Sort data
|
|
_overdrive.data.sortData = function()
|
|
{
|
|
if (_overdrive.ui.sortCol != "") {
|
|
if (_overdrive.data.stringCols.indexOf(_overdrive.ui.sortCol) == -1) {
|
|
if (_overdrive.ui.sortAsc) {
|
|
_overdrive.data.torrents.sort(function(a, b)
|
|
{
|
|
return a[_overdrive.ui.sortCol] - b[_overdrive.ui.sortCol];
|
|
});
|
|
} else {
|
|
_overdrive.data.torrents.sort(function(a, b)
|
|
{
|
|
return b[_overdrive.ui.sortCol] - a[_overdrive.ui.sortCol];
|
|
});
|
|
}
|
|
} else {
|
|
_overdrive.data.torrents.sort(function(a, b)
|
|
{
|
|
return a[_overdrive.ui.sortCol].toLowerCase().localeCompare(b[_overdrive.ui.sortCol].toLowerCase());
|
|
});
|
|
|
|
if (!_overdrive.ui.sortAsc)
|
|
_overdrive.data.torrents.reverse();
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
// Validates the currently selected torrents against the
|
|
// given incoming torrents object
|
|
_overdrive.data.validateSelection = function(newTorrents)
|
|
{
|
|
for (var i = 0; i < _overdrive.data.selected.length; i++) {
|
|
var curTorrent = _overdrive.data.getTorrentById(_overdrive.data.selected[i]);
|
|
var exists = false;
|
|
var display = false;
|
|
for (var j = 0; j < newTorrents.length; j++) {
|
|
if (curTorrent.id == newTorrents[j].id && curTorrent.name == newTorrents[j].name) {
|
|
exists = true;
|
|
if (_overdrive.ui.displayState.indexOf(newTorrents[j].status) != -1)
|
|
display = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!exists || !display) {
|
|
_overdrive.data.selected.splice(i, 1);
|
|
i--;
|
|
}
|
|
}
|
|
};
|
|
|
|
// Attempt to load settings from localStorage
|
|
_overdrive.settings.loadSettings = function()
|
|
{
|
|
if (localStorage.overdriveSideWidth)
|
|
document.getElementById("overdrive-split-side").style.width = localStorage.overdriveSideWidth + "px";
|
|
|
|
if (localStorage.overdriveSplitHeight && localStorage.overdriveListHeight) {
|
|
document.getElementById("overdrive-split").style.height = localStorage.overdriveSplitHeight + "px";
|
|
document.getElementById("overdrive-torrent-list").style.height = (localStorage.overdriveListHeight - _overdrive.ui.listBorder) + "px";
|
|
}
|
|
|
|
if (localStorage.overdriveBinaryKB)
|
|
_overdrive.settings.binaryKB = localStorage.overdriveBinaryKB;
|
|
|
|
/*if (localStorage.overdriveColumns)
|
|
_overdrive.settings.columns = localStorage.overdriveColumns.split(",");*/
|
|
|
|
if (localStorage.overdriveRefreshRate)
|
|
_overdrive.settings.refreshRate = localStorage.overdriveRefreshRate;
|
|
|
|
if (localStorage.overdriveSortCol)
|
|
_overdrive.ui.sortCol = localStorage.overdriveSortCol;
|
|
|
|
if (localStorage.overdriveSortAsc)
|
|
_overdrive.ui.sortAsc = localStorage.overdriveSortAsc;
|
|
};
|
|
|
|
// Save settings to localStorage
|
|
_overdrive.settings.saveSettings = function()
|
|
{
|
|
localStorage.overdriveSideWidth = document.getElementById("overdrive-split-side").clientWidth;
|
|
localStorage.overdriveSplitHeight = document.getElementById("overdrive-split").clientHeight;
|
|
localStorage.overdriveListHeight = document.getElementById("overdrive-torrent-list").offsetHeight;
|
|
localStorage.overdriveBinaryKB = _overdrive.settings.binaryKB;
|
|
localStorage.overdriveColumns = _overdrive.settings.columns;
|
|
localStorage.overdriveRefreshRate = _overdrive.settings.refreshRate;
|
|
localStorage.overdriveSortCol = _overdrive.ui.sortCol;
|
|
localStorage.overdriveSortAsc = _overdrive.ui.sortAsc;
|
|
};
|
|
|
|
// Add button click handler
|
|
_overdrive.ui.addClick = function()
|
|
{
|
|
var menu = document.getElementById("overdrive-add-window");
|
|
menu.style.display = "block";
|
|
document.getElementById("overdrive-add-url").focus();
|
|
|
|
// Make sure window is in the screen
|
|
if (menu.offsetLeft + menu.offsetWidth > window.innerWidth)
|
|
menu.style.left = (window.innerWidth - menu.offsetWidth) + "px";
|
|
if (menu.offsetTop + menu.offsetHeight > window.innerHeight)
|
|
menu.style.top = (window.innerHeight - menu.offsetHeight) + "px";
|
|
};
|
|
|
|
// Click handler for cancel button in add menu
|
|
_overdrive.ui.addCancelClick = function()
|
|
{
|
|
document.getElementById("overdrive-add-form").reset();
|
|
document.getElementById("overdrive-add-window").style.display = "none";
|
|
};
|
|
|
|
// Click handler for upload button in add menu
|
|
_overdrive.ui.addUploadClick = function()
|
|
{
|
|
var addForm = document.getElementById("overdrive-add-form");
|
|
var fileSelect = document.getElementById("overdrive-add-file");
|
|
var urlBox = document.getElementById("overdrive-add-url");
|
|
var started = document.getElementById("overdrive-add-started");
|
|
|
|
if (urlBox.value != "") {
|
|
// Make nyaa.eu more convenient
|
|
if (urlBox.value.indexOf("nyaa.eu" != -1)) {
|
|
urlBox.value = urlBox.value.replace("page=view", "page=download");
|
|
urlBox.value = urlBox.value.replace("page=torrentinfo", "page=download");
|
|
}
|
|
|
|
var request = {};
|
|
request.method = "torrent-add";
|
|
request.arguments = {};
|
|
request.arguments.filename = urlBox.value;
|
|
request.arguments.paused = !started.checked;
|
|
|
|
var xmlhttp;
|
|
if (window.XMLHttpRequest)
|
|
xmlhttp = new XMLHttpRequest();
|
|
else
|
|
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
|
|
|
xmlhttp.open("POST", _overdrive.settings.rpcURL, true);
|
|
xmlhttp.setRequestHeader("X-Transmission-Session-Id", _overdrive.settings.sessionID);
|
|
var postData = JSON.stringify(request);
|
|
xmlhttp.setRequestHeader("Content-type", "application/json");
|
|
xmlhttp.send(postData);
|
|
|
|
xmlhttp.onreadystatechange = function()
|
|
{
|
|
if (xmlhttp.readyState == 4) {
|
|
if (xmlhttp.status == 409) {
|
|
_overdrive.settings.sessionID = xmlhttp.getResponseHeader("X-Transmission-Session-Id");
|
|
alert("Session timed out. Please try again.");
|
|
} else if (xmlhttp.status == 200) {
|
|
var response = JSON.parse(xmlhttp.responseText);
|
|
if (response.result != "success")
|
|
alert("addUploadClick() failed: " + response.result);
|
|
}
|
|
}
|
|
};
|
|
|
|
addForm.reset();
|
|
document.getElementById("overdrive-add-window").style.display = "none";
|
|
}
|
|
};
|
|
|
|
// Alt button click handler
|
|
_overdrive.ui.altClick = function()
|
|
{
|
|
var request = {};
|
|
request.method = "session-set";
|
|
request.arguments = {};
|
|
request.arguments["alt-speed-enabled"] = !_overdrive.data.session["alt-speed-enabled"];
|
|
|
|
var xmlhttp;
|
|
if (window.XMLHttpRequest)
|
|
xmlhttp = new XMLHttpRequest();
|
|
else
|
|
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
|
|
|
xmlhttp.open("POST", _overdrive.settings.rpcURL, true);
|
|
xmlhttp.setRequestHeader("X-Transmission-Session-Id", _overdrive.settings.sessionID);
|
|
var postData = JSON.stringify(request);
|
|
xmlhttp.setRequestHeader("Content-type", "application/json");
|
|
xmlhttp.send(postData);
|
|
|
|
xmlhttp.onreadystatechange = function()
|
|
{
|
|
if (xmlhttp.readyState == 4) {
|
|
if (xmlhttp.status == 409) {
|
|
_overdrive.settings.sessionID = xmlhttp.getResponseHeader("X-Transmission-Session-Id");
|
|
_overdrive.ui.altClick();
|
|
} else if (xmlhttp.status == 200) {
|
|
var response = JSON.parse(xmlhttp.responseText);
|
|
if (response.result != "success")
|
|
alert("altClick() failed: " + response.result);
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
// Delete button click handler
|
|
_overdrive.ui.deleteClick = function()
|
|
{
|
|
if (_overdrive.ui.deleteEnabled) {
|
|
var menu = document.getElementById("overdrive-delete-window");
|
|
menu.style.display = "block";
|
|
|
|
// Make sure window is in the screen
|
|
if (menu.offsetLeft + menu.offsetWidth > window.innerWidth)
|
|
menu.style.left = (window.innerWidth - menu.offsetWidth) + "px";
|
|
if (menu.offsetTop + menu.offsetHeight > window.innerHeight)
|
|
menu.style.top = (window.innerHeight - menu.offsetHeight) + "px";
|
|
}
|
|
};
|
|
|
|
// Delete cancel click handler
|
|
_overdrive.ui.deleteCancelClick = function()
|
|
{
|
|
document.getElementById("overdrive-delete-window").style.display = "none";
|
|
};
|
|
|
|
// Delete confirm click handler
|
|
_overdrive.ui.deleteConfirmClick = function()
|
|
{
|
|
var request = {};
|
|
request.method = "torrent-remove";
|
|
request.arguments = {};
|
|
request.arguments.ids = _overdrive.data.selected;
|
|
request.arguments["delete-local-data"] = document.getElementById("overdrive-delete-data").checked;
|
|
|
|
var xmlhttp;
|
|
if (window.XMLHttpRequest)
|
|
xmlhttp = new XMLHttpRequest();
|
|
else
|
|
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
|
|
|
xmlhttp.open("POST", _overdrive.settings.rpcURL, true);
|
|
xmlhttp.setRequestHeader("X-Transmission-Session-Id", _overdrive.settings.sessionID);
|
|
var postData = JSON.stringify(request);
|
|
xmlhttp.setRequestHeader("Content-type", "application/json");
|
|
xmlhttp.send(postData);
|
|
|
|
xmlhttp.onreadystatechange = function()
|
|
{
|
|
if (xmlhttp.readyState == 4) {
|
|
if (xmlhttp.status == 409) {
|
|
_overdrive.settings.sessionID = xmlhttp.getResponseHeader("X-Transmission-Session-Id");
|
|
_overdrive.ui.deleteConfirmClick();
|
|
} else if (xmlhttp.status == 200) {
|
|
var response = JSON.parse(xmlhttp.responseText);
|
|
if (response.result != "success")
|
|
alert("deleteConfirmClick() failed: " + response.result);
|
|
}
|
|
}
|
|
};
|
|
|
|
document.getElementById("overdrive-delete-window").style.display = "none";
|
|
};
|
|
|
|
// File header column click handler
|
|
_overdrive.ui.fileHeaderColClick = function(event)
|
|
{
|
|
var search = "overdrive-file-column-";
|
|
var colName = event.currentTarget.className.substr(event.currentTarget.className.indexOf(search) + search.length);
|
|
if (colName == _overdrive.ui.fileSortCol) {
|
|
_overdrive.ui.fileSortAsc = !_overdrive.ui.fileSortAsc;
|
|
} else {
|
|
_overdrive.ui.fileSortCol = colName;
|
|
_overdrive.ui.fileSortAsc = true;
|
|
}
|
|
|
|
_overdrive.ui.refreshDetails();
|
|
};
|
|
|
|
// File list scroll handler
|
|
_overdrive.ui.fileListScroll = function()
|
|
{
|
|
_overdrive.ui.fileListScrollY = document.getElementById("overdrive-file-list").scrollTop;
|
|
_overdrive.ui.fileListScrollX = document.getElementById("overdrive-file-list").scrollLeft;
|
|
|
|
document.getElementById("overdrive-file-list-header").style.top = _overdrive.ui.fileListScrollY + "px";
|
|
};
|
|
|
|
// Header column click handler
|
|
_overdrive.ui.headerColClick = function(event)
|
|
{
|
|
var search = "overdrive-column-";
|
|
var colName = event.currentTarget.className.substr(event.currentTarget.className.indexOf(search) + search.length);
|
|
if (colName == _overdrive.ui.sortCol) {
|
|
_overdrive.ui.sortAsc = !_overdrive.ui.sortAsc;
|
|
} else {
|
|
_overdrive.ui.sortCol = colName;
|
|
_overdrive.ui.sortAsc = true;
|
|
}
|
|
|
|
_overdrive.data.sortData();
|
|
_overdrive.ui.refreshList();
|
|
};
|
|
|
|
// Key handler
|
|
_overdrive.ui.keyHandler = function(event)
|
|
{
|
|
// Ctrl+A - Select all torrents
|
|
if (event.ctrlKey && event.which == 65) {
|
|
_overdrive.data.selected = [];
|
|
for (var i = 0; i < _overdrive.data.torrents.length; i++) {
|
|
if (_overdrive.ui.displayState.indexOf(_overdrive.data.torrents[i].status) != -1)
|
|
_overdrive.data.selected.push(_overdrive.data.torrents[i].id);
|
|
}
|
|
|
|
_overdrive.ui.refreshControls();
|
|
_overdrive.ui.refreshList();
|
|
_overdrive.data.getDetailedInfo();
|
|
event.preventDefault();
|
|
}
|
|
};
|
|
|
|
// List click handler
|
|
_overdrive.ui.listClick = function(event)
|
|
{
|
|
if (event.target.id == "overdrive-torrent-list") {
|
|
_overdrive.data.selected = [];
|
|
_overdrive.ui.refreshControls();
|
|
_overdrive.ui.refreshList();
|
|
_overdrive.data.getDetailedInfo();
|
|
}
|
|
};
|
|
|
|
// List scroll event handler
|
|
_overdrive.ui.listScroll = function(event)
|
|
{
|
|
// Keep the header row on top
|
|
_overdrive.ui.listScrollY = document.getElementById("overdrive-torrent-list").scrollTop;
|
|
_overdrive.ui.listScrollX = document.getElementById("overdrive-torrent-list").scrollLeft;
|
|
|
|
document.getElementById("overdrive-torrent-list-header").style.top = _overdrive.ui.listScrollY + "px";
|
|
};
|
|
|
|
// Mouse move event handler
|
|
_overdrive.ui.mouseMove = function(event)
|
|
{
|
|
if (_overdrive.ui.sideResize) {
|
|
var sidePane = document.getElementById("overdrive-split-side");
|
|
sidePane.style.width = (sidePane.clientWidth + (event.clientX - _overdrive.ui.sideLastX)) + "px";
|
|
}
|
|
|
|
if (_overdrive.ui.vertResize) {
|
|
var splitView = document.getElementById("overdrive-split");
|
|
var torList = document.getElementById("overdrive-torrent-list");
|
|
var details = document.getElementById("overdrive-tab-contents");
|
|
splitView.style.height = (splitView.clientHeight + (event.clientY - _overdrive.ui.sideLastY)) + "px";
|
|
torList.style.height = (splitView.clientHeight - (_overdrive.ui.listMargin + _overdrive.ui.listBorder)) + "px";
|
|
var diff = window.innerHeight - document.getElementById("overdrive").clientHeight;
|
|
details.style.height = ((details.clientHeight + diff) - (_overdrive.ui.detailsPadding + _overdrive.ui.detailsMargin)) + "px";
|
|
_overdrive.ui.refreshDetails();
|
|
}
|
|
|
|
if (_overdrive.ui.windowDrag) {
|
|
_overdrive.ui.activeWindow.style.left = (_overdrive.ui.activeWindow.offsetLeft + (event.clientX - _overdrive.ui.sideLastX)) + "px";
|
|
_overdrive.ui.activeWindow.style.top = (_overdrive.ui.activeWindow.offsetTop + (event.clientY - _overdrive.ui.sideLastY)) + "px";
|
|
}
|
|
|
|
_overdrive.ui.sideLastX = event.clientX;
|
|
_overdrive.ui.sideLastY = event.clientY;
|
|
};
|
|
|
|
// Pause click handler
|
|
_overdrive.ui.pauseClick = function()
|
|
{
|
|
if (_overdrive.ui.pauseEnabled) {
|
|
var request = {};
|
|
request.method = "torrent-stop";
|
|
request.arguments = {};
|
|
request.arguments.ids = _overdrive.data.selected;
|
|
|
|
var xmlhttp;
|
|
if (window.XMLHttpRequest)
|
|
xmlhttp = new XMLHttpRequest();
|
|
else
|
|
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
|
|
|
xmlhttp.open("POST", _overdrive.settings.rpcURL, true);
|
|
xmlhttp.setRequestHeader("X-Transmission-Session-Id", _overdrive.settings.sessionID);
|
|
var postData = JSON.stringify(request);
|
|
xmlhttp.setRequestHeader("Content-type", "application/json");
|
|
xmlhttp.send(postData);
|
|
|
|
xmlhttp.onreadystatechange = function()
|
|
{
|
|
if (xmlhttp.readyState == 4) {
|
|
if (xmlhttp.status == 409) {
|
|
_overdrive.settings.sessionID = xmlhttp.getResponseHeader("X-Transmission-Session-Id");
|
|
_overdrive.ui.pauseClick();
|
|
} else if (xmlhttp.status == 200) {
|
|
var response = JSON.parse(xmlhttp.responseText);
|
|
if (response.result != "success")
|
|
alert("pauseClick() failed: " + response.result);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
};
|
|
|
|
// Peer header column click handler
|
|
_overdrive.ui.peerHeaderColClick = function(event)
|
|
{
|
|
var search = "overdrive-peer-column-";
|
|
var colName = event.currentTarget.className.substr(event.currentTarget.className.indexOf(search) + search.length);
|
|
if (colName == _overdrive.ui.peerSortCol) {
|
|
_overdrive.ui.peerSortAsc = !_overdrive.ui.peerSortAsc;
|
|
} else {
|
|
_overdrive.ui.peerSortCol = colName;
|
|
_overdrive.ui.peerSortAsc = true;
|
|
}
|
|
|
|
_overdrive.ui.refreshDetails();
|
|
};
|
|
|
|
// Peer list scroll handler
|
|
_overdrive.ui.peerListScroll = function()
|
|
{
|
|
_overdrive.ui.peerListScrollY = document.getElementById("overdrive-peer-list").scrollTop;
|
|
_overdrive.ui.peerListScrollX = document.getElementById("overdrive-peer-list").scrollLeft;
|
|
|
|
document.getElementById("overdrive-peer-list-header").style.top = _overdrive.ui.peerListScrollY + "px";
|
|
};
|
|
|
|
// Refresh the controls at the top
|
|
_overdrive.ui.refreshControls = function()
|
|
{
|
|
var pauseButton = document.getElementById("overdrive-pause-button");
|
|
var resumeButton = document.getElementById("overdrive-resume-button");
|
|
var deleteButton = document.getElementById("overdrive-delete-button");
|
|
_overdrive.ui.pauseEnabled = false;
|
|
_overdrive.ui.resumeEnabled = false;
|
|
|
|
for (var i = 0; i < _overdrive.data.selected.length; i++) {
|
|
var curTorrent = _overdrive.data.getTorrentById(_overdrive.data.selected[i]);
|
|
if (curTorrent.status == _overdrive.data.torrentStat.stopped)
|
|
_overdrive.ui.resumeEnabled = true;
|
|
else
|
|
_overdrive.ui.pauseEnabled = true;
|
|
}
|
|
|
|
_overdrive.ui.deleteEnabled = (_overdrive.data.selected.length > 0);
|
|
|
|
if (_overdrive.ui.pauseEnabled)
|
|
pauseButton.src = _overdrive.ui.pauseImg;
|
|
else
|
|
pauseButton.src = _overdrive.ui.pauseImgDisabled;
|
|
|
|
if (_overdrive.ui.resumeEnabled)
|
|
resumeButton.src = _overdrive.ui.resumeImg;
|
|
else
|
|
resumeButton.src = _overdrive.ui.resumeImgDisabled;
|
|
|
|
if (_overdrive.ui.deleteEnabled)
|
|
deleteButton.src = _overdrive.ui.deleteImg;
|
|
else
|
|
deleteButton.src = _overdrive.ui.deleteImgDisabled;
|
|
};
|
|
|
|
// Refresh the torrent details section
|
|
_overdrive.ui.refreshDetails = function()
|
|
{
|
|
if (_overdrive.data.selected.length == 0)
|
|
_overdrive.data.torrentsDetail = [];
|
|
|
|
var tab = document.getElementsByClassName("overdrive-tab-active")[0].id;
|
|
tab = tab.slice(tab.indexOf('-') + 1, tab.lastIndexOf('-'));
|
|
var tabContents = document.getElementById("overdrive-tab-contents");
|
|
|
|
if (tab == "status") {
|
|
// Create progress bar
|
|
var canvas = document.getElementById("overdrive-progress-detail");
|
|
canvas.height = canvas.clientHeight;
|
|
canvas.width = canvas.clientWidth;
|
|
|
|
// Calculate totals
|
|
var totalValid = 0, totalUnchecked = 0, totalUp = 0, ratio = 0;
|
|
var announce = 0, tracker = "", totalDownSpeed = 0, totalUpSpeed = 0;
|
|
var eta = -Number.MAX_VALUE, pieces = "", connectedSeeds = 0, totalSeeds = 0;
|
|
var connectedPeers = 0, totalPeers = 0, availability = 0;
|
|
var activeTime = 0, seedTime = 0;
|
|
for (var i = 0; i < _overdrive.data.torrentsDetail.length; i++) {
|
|
totalValid += _overdrive.data.torrentsDetail[i].haveValid;
|
|
totalUnchecked += _overdrive.data.torrentsDetail[i].haveUnchecked;
|
|
totalUp += _overdrive.data.torrentsDetail[i].uploadedEver;
|
|
totalDownSpeed += _overdrive.data.torrentsDetail[i].rateDownload;
|
|
totalUpSpeed += _overdrive.data.torrentsDetail[i].rateUpload;
|
|
activeTime += _overdrive.data.torrentsDetail[i].secondsDownloading;
|
|
activeTime += _overdrive.data.torrentsDetail[i].secondsSeeding;
|
|
seedTime += _overdrive.data.torrentsDetail[i].secondsSeeding;
|
|
availability = (Number(availability) + _overdrive.data.torrentsDetail[i].percentDone).toFixed(4);
|
|
|
|
for (var j = 0; j < _overdrive.data.torrentsDetail[i].peers.length; j++) {
|
|
availability = (Number(availability) + _overdrive.data.torrentsDetail[i].peers[j].progress).toFixed(4);
|
|
if (_overdrive.data.torrentsDetail[i].peers[j].progress == 1)
|
|
connectedSeeds++;
|
|
else
|
|
connectedPeers++;
|
|
}
|
|
|
|
ratio = _overdrive.data.torrentsDetail[i].uploadRatio.toFixed(4);
|
|
announce = Number.MAX_VALUE;
|
|
for (var j = 0; j < _overdrive.data.torrentsDetail[i].trackerStats.length; j++) {
|
|
if (_overdrive.data.torrentsDetail[i].trackerStats[j].nextAnnounceTime < announce)
|
|
announce = _overdrive.data.friendlyTimeString(_overdrive.data.torrentsDetail[i].trackerStats[j].nextAnnounceTime - (new Date().getTime() / 1000));
|
|
tracker += _overdrive.data.torrentsDetail[i].trackerStats[j].host;
|
|
tracker += " - ";
|
|
if (_overdrive.data.torrentsDetail[i].trackerStats[j].lastAnnounceResult == "Success")
|
|
tracker += "<span class='overdrive-success-string'>";
|
|
else
|
|
tracker += "<span class='overdrive-fail-string'>";
|
|
tracker += _overdrive.data.torrentsDetail[i].trackerStats[j].lastAnnounceResult;
|
|
tracker += "</span><br />";
|
|
|
|
if (_overdrive.data.torrentsDetail[i].trackerStats[j].seederCount > 0)
|
|
totalSeeds += _overdrive.data.torrentsDetail[i].trackerStats[j].seederCount;
|
|
if (_overdrive.data.torrentsDetail[i].trackerStats[j].leecherCount > 0)
|
|
totalPeers += _overdrive.data.torrentsDetail[i].trackerStats[j].leecherCount;
|
|
}
|
|
|
|
if (_overdrive.data.torrentsDetail[i].eta > eta)
|
|
eta = _overdrive.data.torrentsDetail[i].eta;
|
|
pieces = _overdrive.data.torrentsDetail[i].pieceCount;
|
|
pieces += " (";
|
|
pieces += _overdrive.data.friendlyByteString(_overdrive.data.torrentsDetail[i].pieceSize);
|
|
pieces += ")";
|
|
|
|
if (i != 0) {
|
|
ratio = "";
|
|
announce = "";
|
|
tracker = "";
|
|
pieces = "";
|
|
availability = "";
|
|
ratio = (totalUp / totalValid).toFixed(4);
|
|
}
|
|
}
|
|
|
|
// Define table information
|
|
var tableInfo = [
|
|
[
|
|
[
|
|
"Downloaded:",
|
|
_overdrive.data.friendlyByteString(totalValid) + " (" +
|
|
_overdrive.data.friendlyByteString(totalUnchecked) + ")"
|
|
], [
|
|
"Uploaded:",
|
|
_overdrive.data.friendlyByteString(totalUp)
|
|
], [
|
|
"Share Ratio:",
|
|
ratio
|
|
], [
|
|
"Next Announce:",
|
|
announce
|
|
], [
|
|
"Tracker Status:",
|
|
tracker
|
|
]
|
|
], [
|
|
[
|
|
"Down Speed:",
|
|
_overdrive.data.friendlyByteString(totalDownSpeed) + "/s"
|
|
], [
|
|
"Up Speed:",
|
|
_overdrive.data.friendlyByteString(totalUpSpeed) + "/s"
|
|
], [
|
|
"ETA:",
|
|
_overdrive.data.friendlyTimeString(eta)
|
|
], [
|
|
"Pieces:",
|
|
pieces
|
|
]
|
|
], [
|
|
[
|
|
"Seeders:",
|
|
connectedSeeds + " (" + totalSeeds + ")"
|
|
], [
|
|
"Peers:",
|
|
connectedPeers + " (" + totalPeers + ")"
|
|
], [
|
|
"Availability:",
|
|
availability
|
|
]
|
|
], [
|
|
[
|
|
"Active Time:",
|
|
_overdrive.data.friendlyTimeString(activeTime)
|
|
], [
|
|
"Seeding Time:",
|
|
_overdrive.data.friendlyTimeString(seedTime)
|
|
]
|
|
]
|
|
];
|
|
|
|
// Create table
|
|
var statusTable = document.getElementById("overdrive-status-table");
|
|
statusTable.style.height = (Number(tabContents.style.height.slice(0, -2)) - canvas.height) + "px";
|
|
statusTable.innerHTML = "";
|
|
var statusTableBody = document.createElement("tbody");
|
|
var statusTableBodyRow = document.createElement("tr");
|
|
|
|
for (var i = 0; i < tableInfo.length; i++) {
|
|
var statusTableBodyCol = document.createElement("td");
|
|
statusTableBodyCol.style.width = (statusTable.clientWidth / tableInfo.length) + "px";
|
|
var colTable = document.createElement("table");
|
|
var colTableBody = document.createElement("tbody");
|
|
|
|
for (var j = 0; j < tableInfo[i].length; j++) {
|
|
var row = document.createElement("tr");
|
|
var rowTitle = document.createElement("td");
|
|
var rowBody = document.createElement("td");
|
|
|
|
rowTitle.innerHTML = tableInfo[i][j][0];
|
|
if (_overdrive.data.torrentsDetail.length == 0)
|
|
rowBody.innerHTML = "";
|
|
else
|
|
rowBody.innerHTML = tableInfo[i][j][1];
|
|
|
|
row.appendChild(rowTitle);
|
|
row.appendChild(rowBody);
|
|
colTableBody.appendChild(row);
|
|
}
|
|
|
|
colTable.appendChild(colTableBody);
|
|
statusTableBodyCol.appendChild(colTable);
|
|
statusTableBodyRow.appendChild(statusTableBodyCol);
|
|
}
|
|
|
|
statusTableBody.appendChild(statusTableBodyRow);
|
|
statusTable.appendChild(statusTableBody);
|
|
statusTable.scrollTop = _overdrive.ui.statusTablePos;
|
|
|
|
// Draw to progress bar
|
|
var ctx = canvas.getContext("2d");
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
if (_overdrive.data.torrentsDetail.length == 1) {
|
|
ctx.fillStyle = _overdrive.ui.canvasColor;
|
|
var bits = _overdrive.data.base64ToBits(_overdrive.data.torrentsDetail[0].pieces);
|
|
var len = _overdrive.data.torrentsDetail[0].pieceCount;
|
|
var i = 0, count = 0, cont = -1;
|
|
while (i < len) {
|
|
if (cont >= 0) {
|
|
if (bits.charAt(i) == '1')
|
|
count++;
|
|
|
|
if (bits.charAt(i) == '0' || i == len - 1) {
|
|
ctx.fillRect(cont / len * canvas.width, 0, count / len * canvas.width, canvas.height);
|
|
cont = -1;
|
|
}
|
|
} else {
|
|
if (bits.charAt(i) == '1') {
|
|
cont = i;
|
|
count = 1;
|
|
}
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
var str = _overdrive.data.torrentsDetail[0].statusHTML + " " + _overdrive.data.torrentsDetail[0].percentDoneHTML;
|
|
ctx.font = _overdrive.ui.fontSize + " " + _overdrive.ui.fontFamily;
|
|
ctx.fillStyle = _overdrive.ui.fontColor;
|
|
ctx.textAlign = "center";
|
|
ctx.textBaseline = "middle";
|
|
ctx.fillText(str, canvas.width / 2, canvas.height / 2);
|
|
} else if (_overdrive.data.torrentsDetail.length > 1) {
|
|
ctx.font = _overdrive.ui.fontSize + " " + _overdrive.ui.fontFamily;
|
|
ctx.fillStyle = _overdrive.ui.fontColor;
|
|
ctx.textAlign = "center";
|
|
ctx.textBaseline = "middle";
|
|
ctx.fillText("Multiple selected", canvas.width / 2, canvas.height / 2);
|
|
}
|
|
} else if (tab == "files") {
|
|
var files = [];
|
|
for (var i = 0; i < _overdrive.data.torrentsDetail.length; i++) {
|
|
for (var j = 0; j < _overdrive.data.torrentsDetail[i].files.length; j++) {
|
|
var curFile = {};
|
|
curFile.name = _overdrive.data.torrentsDetail[i].files[j].name;
|
|
var slashInd = curFile.name.lastIndexOf("/");
|
|
if (slashInd != -1) {
|
|
curFile.nameHTML = "<span class='overdrive-folder-string'>" + curFile.name.substr(0, slashInd + 1) + "</span>";
|
|
curFile.nameHTML += curFile.name.substr(slashInd + 1);
|
|
} else {
|
|
curFile.nameHTML = curFile.name;
|
|
}
|
|
curFile.totalSize = _overdrive.data.torrentsDetail[i].files[j].length;
|
|
curFile.totalSizeHTML = _overdrive.data.friendlyByteString(curFile.totalSize);
|
|
curFile.percentDone = _overdrive.data.torrentsDetail[i].files[j].bytesCompleted / _overdrive.data.torrentsDetail[i].files[j].length;
|
|
curFile.percentDoneHTML = (curFile.percentDone * 100).toFixed(2) + "%";
|
|
curFile.wanted = _overdrive.data.torrentsDetail[i].fileStats[j].wanted
|
|
curFile.wantedHTML = "<input id='overdrive-file-wanted-" + _overdrive.data.torrentsDetail[i].id + "-" + j + "' ";
|
|
curFile.wantedHTML += "class='overdrive-file-wanted' type='checkbox' ";
|
|
if (curFile.wanted)
|
|
curFile.wantedHTML += "checked ";
|
|
curFile.wantedHTML += "/>";
|
|
files[files.length] = curFile;
|
|
}
|
|
}
|
|
|
|
var fileList = document.getElementById("overdrive-file-list");
|
|
fileList.style.height = tabContents.style.height;
|
|
var fileListHeader = document.getElementById("overdrive-file-list-header");
|
|
fileListHeader.innerHTML = "";
|
|
|
|
var columns = ["name", "totalSize", "wanted", "percentDone"];
|
|
var stringCols = ["name"];
|
|
var columnNames = {};
|
|
columnNames.name = "Filename";
|
|
columnNames.totalSize = "Size";
|
|
columnNames.wanted = "Wanted";
|
|
columnNames.percentDone = "Progress";
|
|
|
|
// Sort files
|
|
if (stringCols.indexOf(_overdrive.ui.fileSortCol) == -1) {
|
|
if (_overdrive.ui.fileSortAsc) {
|
|
files.sort(function(a, b)
|
|
{
|
|
return a[_overdrive.ui.fileSortCol] - b[_overdrive.ui.fileSortCol];
|
|
});
|
|
} else {
|
|
files.sort(function(a, b)
|
|
{
|
|
return b[_overdrive.ui.fileSortCol] - a[_overdrive.ui.fileSortCol];
|
|
});
|
|
}
|
|
} else {
|
|
files.sort(function(a, b)
|
|
{
|
|
return a[_overdrive.ui.fileSortCol].toLowerCase().localeCompare(b[_overdrive.ui.fileSortCol].toLowerCase());
|
|
});
|
|
|
|
if (!_overdrive.ui.fileSortAsc)
|
|
files.reverse();
|
|
}
|
|
|
|
for (var i = 0; i < columns.length; i++) {
|
|
var column = document.createElement("div");
|
|
column.className = "overdrive-header-column overdrive-file-column-" + columns[i];
|
|
column.onmousedown = _overdrive.ui.fileHeaderColClick;
|
|
column.innerHTML = columnNames[columns[i]];
|
|
fileListHeader.appendChild(column);
|
|
}
|
|
|
|
var fileListBody = document.getElementById("overdrive-file-list-body");
|
|
fileListBody.innerHTML = "";
|
|
|
|
for (var i = 0; i < files.length; i++) {
|
|
var curFile = document.createElement("div");
|
|
curFile.className = "overdrive-file overdrive-table-entry";
|
|
|
|
for (var j = 0; j < columns.length; j++) {
|
|
var curCol = document.createElement("div");
|
|
curCol.className = "overdrive-file-column-" + columns[j];
|
|
curCol.innerHTML = files[i][columns[j] + "HTML"];
|
|
curFile.appendChild(curCol);
|
|
}
|
|
|
|
fileListBody.appendChild(curFile);
|
|
fileListBody.appendChild(document.createElement("br"));
|
|
}
|
|
|
|
// Attach event handlers to wanted checkboxes
|
|
var wantedBoxes = document.getElementsByClassName("overdrive-file-wanted");
|
|
for (var i = 0; i < wantedBoxes.length; i++)
|
|
wantedBoxes[i].onchange = _overdrive.ui.wantedBoxClick;
|
|
|
|
for (var i = 0; i < columns.length; i++) {
|
|
var maxWidth = 0;
|
|
var cells = document.getElementsByClassName("overdrive-file-column-" + columns[i]);
|
|
for (var j = 0; j < cells.length; j++)
|
|
maxWidth = Math.max(maxWidth, cells[j].scrollWidth - _overdrive.ui.tableCellPadding);
|
|
for (var j = 0; j < cells.length; j++)
|
|
cells[j].style.width = maxWidth + "px";
|
|
}
|
|
|
|
fileList.scrollTop = _overdrive.ui.fileListScrollY;
|
|
fileList.scrollLeft = _overdrive.ui.fileListScrollX;
|
|
} else if (tab == "peers") {
|
|
var peers = [];
|
|
for (var i = 0; i < _overdrive.data.torrentsDetail.length; i++) {
|
|
for (var j = 0; j < _overdrive.data.torrentsDetail[i].peers.length; j++) {
|
|
var curPeer = {};
|
|
addressSeg = _overdrive.data.torrentsDetail[i].peers[j].address.split(".");
|
|
curPeer.address = Number(addressSeg[3]);
|
|
curPeer.address += Number(addressSeg[2]) << 8;
|
|
curPeer.address += Number(addressSeg[1]) << 16;
|
|
// Adding >>> 0 to the end makes the result get interpreted as unsigned
|
|
// This is necessary when addressSeg[0] is 128 or higher (aka the upper half of IPv4 addresses)
|
|
curPeer.address += Number(addressSeg[0]) << 24 >>> 0;
|
|
curPeer.address += "." + _overdrive.data.torrentsDetail[i].peers[j].port;
|
|
curPeer.address = Number(curPeer.address);
|
|
curPeer.addressHTML = _overdrive.data.torrentsDetail[i].peers[j].address;
|
|
curPeer.addressHTML += ":" + _overdrive.data.torrentsDetail[i].peers[j].port;
|
|
curPeer.clientName = _overdrive.data.torrentsDetail[i].peers[j].clientName;
|
|
curPeer.clientNameHTML = curPeer.clientName;
|
|
curPeer.progress = _overdrive.data.torrentsDetail[i].peers[j].progress;
|
|
curPeer.progressHTML = (curPeer.progress * 100).toFixed(2) + "%";
|
|
curPeer.rateToClient = _overdrive.data.torrentsDetail[i].peers[j].rateToClient;
|
|
curPeer.rateToClientHTML = _overdrive.data.friendlyByteString(curPeer.rateToClient) + "/s";
|
|
curPeer.rateToPeer = _overdrive.data.torrentsDetail[i].peers[j].rateToPeer;
|
|
curPeer.rateToPeerHTML = _overdrive.data.friendlyByteString(curPeer.rateToPeer) + "/s";
|
|
peers[peers.length] = curPeer;
|
|
}
|
|
}
|
|
|
|
var peerList = document.getElementById("overdrive-peer-list");
|
|
peerList.style.height = tabContents.style.height;
|
|
var peerListHeader = document.getElementById("overdrive-peer-list-header");
|
|
peerListHeader.innerHTML = "";
|
|
|
|
var columns = ["address", "clientName", "progress", "rateToClient", "rateToPeer"];
|
|
var stringCols = ["clientName"];
|
|
var columnNames = {};
|
|
columnNames.address = "Address";
|
|
columnNames.clientName = "Client";
|
|
columnNames.progress = "Progress";
|
|
columnNames.rateToClient = "Down Speed";
|
|
columnNames.rateToPeer = "Up Speed";
|
|
|
|
// Sort peers
|
|
if (stringCols.indexOf(_overdrive.ui.peerSortCol) == -1) {
|
|
if (_overdrive.ui.peerSortAsc) {
|
|
peers.sort(function(a, b)
|
|
{
|
|
return a[_overdrive.ui.peerSortCol] - b[_overdrive.ui.peerSortCol];
|
|
});
|
|
} else {
|
|
peers.sort(function(a, b)
|
|
{
|
|
return b[_overdrive.ui.peerSortCol] - a[_overdrive.ui.peerSortCol];
|
|
});
|
|
}
|
|
} else {
|
|
peers.sort(function(a, b)
|
|
{
|
|
return a[_overdrive.ui.peerSortCol].toLowerCase().localeCompare(b[_overdrive.ui.peerSortCol].toLowerCase());
|
|
});
|
|
|
|
if (!_overdrive.ui.peerSortAsc)
|
|
peers.reverse();
|
|
}
|
|
|
|
for (var i = 0; i < columns.length; i++) {
|
|
var column = document.createElement("div");
|
|
column.className = "overdrive-header-column overdrive-peer-column-" + columns[i];
|
|
column.onmousedown = _overdrive.ui.peerHeaderColClick;
|
|
column.innerHTML = columnNames[columns[i]];
|
|
peerListHeader.appendChild(column);
|
|
}
|
|
|
|
var peerListBody = document.getElementById("overdrive-peer-list-body");
|
|
peerListBody.innerHTML = "";
|
|
|
|
for (var i = 0; i < peers.length; i++) {
|
|
var curPeer = document.createElement("div");
|
|
curPeer.className = "overdrive-peer overdrive-table-entry";
|
|
|
|
for (var j = 0; j < columns.length; j++) {
|
|
var curCol = document.createElement("div");
|
|
curCol.className = "overdrive-peer-column-" + columns[j];
|
|
curCol.innerHTML = peers[i][columns[j] + "HTML"];
|
|
curPeer.appendChild(curCol);
|
|
}
|
|
|
|
peerListBody.appendChild(curPeer);
|
|
peerListBody.appendChild(document.createElement("br"));
|
|
}
|
|
|
|
for (var i = 0; i < columns.length; i++) {
|
|
var maxWidth = 0;
|
|
var cells = document.getElementsByClassName("overdrive-peer-column-" + columns[i]);
|
|
for (var j = 0; j < cells.length; j++)
|
|
maxWidth = Math.max(maxWidth, cells[j].scrollWidth - _overdrive.ui.tableCellPadding);
|
|
for (var j = 0; j < cells.length; j++)
|
|
cells[j].style.width = maxWidth + "px";
|
|
}
|
|
|
|
peerList.scrollTop = _overdrive.ui.peerListScrollY;
|
|
peerList.scrollLeft = _overdrive.ui.peerListScrollX;
|
|
}
|
|
};
|
|
|
|
// Refresh the torrent and state lists
|
|
_overdrive.ui.refreshList = function()
|
|
{
|
|
var header = document.getElementById("overdrive-torrent-list-header");
|
|
header.innerHTML = "";
|
|
var list = document.getElementById("overdrive-torrent-list-body");
|
|
list.innerHTML = "";
|
|
var downloadCount = 0;
|
|
var seedCount = 0;
|
|
var activeCount = 0;
|
|
var pauseCount = 0;
|
|
|
|
// Generate list header
|
|
for (var i = 0; i < _overdrive.settings.columns.length; i++) {
|
|
var cell = document.createElement("div");
|
|
cell.className = "overdrive-header-column overdrive-column-" + _overdrive.settings.columns[i];
|
|
cell.innerHTML = _overdrive.data.columnNames[_overdrive.settings.columns[i]];
|
|
cell.onmousedown = _overdrive.ui.headerColClick;
|
|
header.appendChild(cell);
|
|
}
|
|
|
|
// Generate list body
|
|
for (var i = 0; i < _overdrive.data.torrents.length; i++) {
|
|
if (_overdrive.ui.displayState.indexOf(_overdrive.data.torrents[i].status) != -1) {
|
|
var row = document.createElement("div");
|
|
row.id = "overdrive-torrent-" + _overdrive.data.torrents[i].id;
|
|
row.className = "overdrive-torrent overdrive-table-entry";
|
|
if (_overdrive.data.selected.indexOf(_overdrive.data.torrents[i].id) != -1)
|
|
row.className += " overdrive-torrent-selected";
|
|
|
|
for (var j = 0; j < _overdrive.settings.columns.length; j++) {
|
|
var cell = document.createElement("div");
|
|
cell.className = "overdrive-column-" + _overdrive.settings.columns[j];
|
|
cell.innerHTML = _overdrive.data.torrents[i][_overdrive.settings.columns[j] + "HTML"];
|
|
row.appendChild(cell);
|
|
}
|
|
|
|
row.onmousedown = _overdrive.ui.torrentClick;
|
|
list.appendChild(row);
|
|
list.appendChild(document.createElement("br"));
|
|
}
|
|
|
|
switch (_overdrive.data.torrents[i].status) {
|
|
case _overdrive.data.torrentStat.stopped:
|
|
pauseCount++;
|
|
break;
|
|
case _overdrive.data.torrentStat.downloadWait:
|
|
downloadCount++;
|
|
break;
|
|
case _overdrive.data.torrentStat.download:
|
|
activeCount++;
|
|
downloadCount++;
|
|
break;
|
|
case _overdrive.data.torrentStat.seedWait:
|
|
seedCount++;
|
|
break;
|
|
case _overdrive.data.torrentStat.seed:
|
|
activeCount++;
|
|
seedCount++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Update state counters
|
|
document.getElementById("overdrive-state-all").innerHTML = "All (" + _overdrive.data.torrents.length + ")";
|
|
document.getElementById("overdrive-state-downloading").innerHTML = "Downloading (" + downloadCount + ")";
|
|
document.getElementById("overdrive-state-seeding").innerHTML = "Seeding (" + seedCount + ")";
|
|
document.getElementById("overdrive-state-active").innerHTML = "Active (" + activeCount + ")";
|
|
document.getElementById("overdrive-state-paused").innerHTML = "Paused (" + pauseCount + ")";
|
|
|
|
// Auto-resize list columns
|
|
for (var i = 0; i < _overdrive.settings.columns.length; i++) {
|
|
var maxWidth = 0;
|
|
var cols = document.getElementsByClassName("overdrive-column-" + _overdrive.settings.columns[i]);
|
|
for (var j = 0; j < cols.length; j++)
|
|
maxWidth = Math.max(maxWidth, cols[j].scrollWidth - _overdrive.ui.tableCellPadding);
|
|
for (var j = 0; j < cols.length; j++)
|
|
cols[j].style.width = maxWidth + "px";
|
|
}
|
|
|
|
document.getElementById("overdrive-torrent-list").scrollTop = _overdrive.ui.listScrollY;
|
|
document.getElementById("overdrive-torrent-list").scrollLeft = _overdrive.ui.listScrollX;
|
|
};
|
|
|
|
// Refresh settings windows
|
|
_overdrive.ui.refreshSettings = function()
|
|
{
|
|
if (_overdrive.data.session["alt-speed-enabled"])
|
|
document.getElementById("overdrive-alt-button").src = _overdrive.ui.altImg;
|
|
else
|
|
document.getElementById("overdrive-alt-button").src = _overdrive.ui.altImgDisabled;
|
|
};
|
|
|
|
// Resize handler
|
|
_overdrive.ui.resize = function()
|
|
{
|
|
// Redraw the details pane
|
|
_overdrive.ui.refreshDetails();
|
|
|
|
// Make sure floating menus are still in the screen
|
|
var menus = document.getElementsByClassName("overdrive-window");
|
|
for (var i = 0; i < menus.length; i++) {
|
|
if (menus[i].offsetLeft + menus[i].offsetWidth > window.innerWidth)
|
|
menus[i].style.left = (window.innerWidth - menus[i].offsetWidth) + "px";
|
|
if (menus[i].offsetTop + menus[i].offsetHeight > window.innerHeight)
|
|
menus[i].style.top = (window.innerHeight - menus[i].offsetHeight) + "px";
|
|
}
|
|
|
|
// Resize the details pane with the window
|
|
var splitView = document.getElementById("overdrive-split");
|
|
var torList = document.getElementById("overdrive-torrent-list");
|
|
var details = document.getElementById("overdrive-tab-contents");
|
|
splitView.style.height = (splitView.clientHeight + (window.innerHeight - _overdrive.ui.lastHeight)) + "px";
|
|
torList.style.height = (splitView.clientHeight - (_overdrive.ui.listMargin + _overdrive.ui.listBorder)) + "px";
|
|
var diff = window.innerHeight - document.getElementById("overdrive").clientHeight;
|
|
details.style.height = ((details.clientHeight + diff) - (_overdrive.ui.detailsPadding + _overdrive.ui.detailsMargin)) + "px";
|
|
|
|
_overdrive.ui.lastHeight = window.innerHeight;
|
|
_overdrive.ui.lastWidth = window.innerWidth;
|
|
};
|
|
|
|
// Resume click handler
|
|
_overdrive.ui.resumeClick = function()
|
|
{
|
|
if (_overdrive.ui.resumeEnabled) {
|
|
var request = {};
|
|
request.method = "torrent-start";
|
|
request.arguments = {};
|
|
request.arguments.ids = _overdrive.data.selected;
|
|
|
|
var xmlhttp;
|
|
if (window.XMLHttpRequest)
|
|
xmlhttp = new XMLHttpRequest();
|
|
else
|
|
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
|
|
|
xmlhttp.open("POST", _overdrive.settings.rpcURL, true);
|
|
xmlhttp.setRequestHeader("X-Transmission-Session-Id", _overdrive.settings.sessionID);
|
|
var postData = JSON.stringify(request);
|
|
xmlhttp.setRequestHeader("Content-type", "application/json");
|
|
xmlhttp.send(postData);
|
|
|
|
xmlhttp.onreadystatechange = function()
|
|
{
|
|
if (xmlhttp.readyState == 4) {
|
|
if (xmlhttp.status == 409) {
|
|
_overdrive.settings.sessionID = xmlhttp.getResponseHeader("X-Transmission-Session-Id");
|
|
_overdrive.ui.resumeClick();
|
|
} else if (xmlhttp.status == 200) {
|
|
var response = JSON.parse(xmlhttp.responseText);
|
|
if (response.result != "success")
|
|
alert("resumeClick() failed: " + response.result);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
};
|
|
|
|
// State click handler
|
|
_overdrive.ui.stateClick = function(event)
|
|
{
|
|
var state = event.currentTarget.id.substr("overdrive-state-".length);
|
|
if (event.currentTarget.className.search("overdrive-state-active") != -1)
|
|
return;
|
|
|
|
if (state == "all") {
|
|
_overdrive.ui.displayState = [
|
|
_overdrive.data.torrentStat.stopped,
|
|
_overdrive.data.torrentStat.checkWait,
|
|
_overdrive.data.torrentStat.check,
|
|
_overdrive.data.torrentStat.downloadWait,
|
|
_overdrive.data.torrentStat.download,
|
|
_overdrive.data.torrentStat.seedWait,
|
|
_overdrive.data.torrentStat.seed
|
|
];
|
|
}
|
|
else if (state == "downloading") {
|
|
_overdrive.ui.displayState = [
|
|
_overdrive.data.torrentStat.downloadWait,
|
|
_overdrive.data.torrentStat.download
|
|
];
|
|
}
|
|
else if (state == "seeding") {
|
|
_overdrive.ui.displayState = [
|
|
_overdrive.data.torrentStat.seedWait,
|
|
_overdrive.data.torrentStat.seed
|
|
];
|
|
}
|
|
else if (state == "active") {
|
|
_overdrive.ui.displayState = [
|
|
_overdrive.data.torrentStat.download,
|
|
_overdrive.data.torrentStat.seed
|
|
];
|
|
}
|
|
else if (state == "paused")
|
|
_overdrive.ui.displayState = [_overdrive.data.torrentStat.stopped];
|
|
|
|
var stateLabels = document.getElementsByClassName("overdrive-state");
|
|
for (var i = 0; i < stateLabels.length; i++) {
|
|
var className = "overdrive-state";
|
|
if (stateLabels[i] == event.currentTarget)
|
|
className += " overdrive-state-active";
|
|
stateLabels[i].className = className;
|
|
}
|
|
|
|
_overdrive.data.selected = [];
|
|
_overdrive.ui.refreshControls();
|
|
_overdrive.ui.refreshList();
|
|
_overdrive.data.getDetailedInfo();
|
|
};
|
|
|
|
// Status table scroll handler
|
|
_overdrive.ui.statusTableScroll = function()
|
|
{
|
|
_overdrive.ui.statusTablePos = document.getElementById("overdrive-status-table").scrollTop;
|
|
};
|
|
|
|
// Tab click handler
|
|
_overdrive.ui.tabClick = function(event)
|
|
{
|
|
var activeTab = document.getElementsByClassName("overdrive-tab-active")[0];
|
|
if (event.currentTarget != activeTab) {
|
|
activeTab.className = "overdrive-tab";
|
|
event.currentTarget.className += " overdrive-tab-active";
|
|
|
|
var tab = event.currentTarget.id;
|
|
tab = tab.slice(tab.indexOf('-') + 1, tab.lastIndexOf('-'));
|
|
var tabContents = document.getElementById("overdrive-tab-contents");
|
|
tabContents.innerHTML = "";
|
|
|
|
if (tab == "status") {
|
|
var canvas = document.createElement("canvas");
|
|
canvas.id = "overdrive-progress-detail";
|
|
tabContents.appendChild(canvas);
|
|
|
|
var statusTable = document.createElement("table");
|
|
statusTable.id = "overdrive-status-table";
|
|
statusTable.onscroll = _overdrive.ui.statusTableScroll;
|
|
tabContents.appendChild(statusTable);
|
|
} else if (tab == "files") {
|
|
var fileList = document.createElement("div");
|
|
fileList.id = "overdrive-file-list";
|
|
fileList.className = "overdrive-table";
|
|
fileList.onscroll = _overdrive.ui.fileListScroll;
|
|
|
|
var fileListHeader = document.createElement("div");
|
|
fileListHeader.id = "overdrive-file-list-header";
|
|
fileListHeader.className = "overdrive-table-header";
|
|
var loading = document.createElement("div");
|
|
loading.innerHTML = "Loading...";
|
|
fileListHeader.appendChild(loading);
|
|
fileList.appendChild(fileListHeader);
|
|
tabContents.appendChild(fileList);
|
|
|
|
var fileListBody = document.createElement("div");
|
|
fileListBody.id = "overdrive-file-list-body";
|
|
fileListBody.className = "overdrive-table-body";
|
|
fileListBody.style.paddingTop = fileListHeader.offsetHeight + "px";
|
|
fileList.appendChild(fileListBody);
|
|
} else if (tab == "peers") {
|
|
var peerList = document.createElement("div");
|
|
peerList.id = "overdrive-peer-list";
|
|
peerList.className = "overdrive-table";
|
|
peerList.onscroll = _overdrive.ui.peerListScroll;
|
|
|
|
var peerListHeader = document.createElement("div");
|
|
peerListHeader.id = "overdrive-peer-list-header";
|
|
peerListHeader.className = "overdrive-table-header";
|
|
var loading = document.createElement("div");
|
|
loading.innerHTML = "Loading...";
|
|
peerListHeader.appendChild(loading);
|
|
peerList.appendChild(peerListHeader);
|
|
tabContents.appendChild(peerList);
|
|
|
|
var peerListBody = document.createElement("div");
|
|
peerListBody.id = "overdrive-peer-list-body";
|
|
peerListBody.className = "overdrive-table-body";
|
|
peerListBody.style.paddingTop = peerListHeader.offsetHeight + "px";
|
|
peerList.appendChild(peerListBody);
|
|
} else {
|
|
tabContents.innerHTML += tab;
|
|
}
|
|
|
|
_overdrive.ui.refreshDetails();
|
|
}
|
|
};
|
|
|
|
// Torrent click handler (for selecting torrents)
|
|
_overdrive.ui.torrentClick = function(event)
|
|
{
|
|
var num = Number(event.currentTarget.id.substr("overdrive-torrent-".length));
|
|
|
|
if (!event.ctrlKey)
|
|
_overdrive.data.selected = [];
|
|
|
|
if (event.shiftKey) {
|
|
if (_overdrive.ui.lastClickedTorrent == -1) {
|
|
_overdrive.data.selected.push(num);
|
|
} else {
|
|
var numInd = _overdrive.data.indexOfID(num);
|
|
var lastInd = _overdrive.data.indexOfID(_overdrive.ui.lastClickedTorrent);
|
|
var start, end;
|
|
if (numInd > lastInd) {
|
|
start = lastInd;
|
|
end = numInd;
|
|
} else {
|
|
start = numInd;
|
|
end = lastInd;
|
|
}
|
|
|
|
for (var i = start; i <= end; i++) {
|
|
if (_overdrive.ui.displayState.indexOf(_overdrive.data.torrents[i].status) != -1)
|
|
_overdrive.data.selected.push(_overdrive.data.torrents[i].id);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (event.ctrlKey) {
|
|
var index = _overdrive.data.selected.indexOf(num);
|
|
if (index == -1)
|
|
_overdrive.data.selected.push(num);
|
|
else
|
|
_overdrive.data.selected.splice(index, 1);
|
|
} else {
|
|
_overdrive.data.selected.push(num);
|
|
}
|
|
|
|
_overdrive.ui.lastClickedTorrent = num;
|
|
}
|
|
|
|
_overdrive.ui.fileListScrollX = 0;
|
|
_overdrive.ui.fileListScrollY = 0;
|
|
_overdrive.ui.peerListScrollX = 0;
|
|
_overdrive.ui.peerListScrollY = 0;
|
|
_overdrive.ui.statusTablePos = 0;
|
|
_overdrive.ui.refreshList();
|
|
_overdrive.ui.refreshControls();
|
|
_overdrive.data.getDetailedInfo();
|
|
|
|
event.preventDefault();
|
|
};
|
|
|
|
// File wanted checkbox click handler
|
|
_overdrive.ui.wantedBoxClick = function(event)
|
|
{
|
|
var boxID = event.currentTarget.id.split("-");
|
|
var torrentID = Number(boxID[boxID.length - 2]);
|
|
var fileID = Number(boxID[boxID.length - 1]);
|
|
|
|
var request = {};
|
|
request.method = "torrent-set";
|
|
request.arguments = {};
|
|
request.arguments.ids = [torrentID];
|
|
if (event.currentTarget.checked)
|
|
request.arguments["files-wanted"] = [fileID];
|
|
else
|
|
request.arguments["files-unwanted"] = [fileID];
|
|
|
|
var xmlhttp;
|
|
if (window.XMLHttpRequest)
|
|
xmlhttp = new XMLHttpRequest();
|
|
else
|
|
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
|
|
|
xmlhttp.open("POST", _overdrive.settings.rpcURL, true);
|
|
xmlhttp.setRequestHeader("X-Transmission-Session-Id", _overdrive.settings.sessionID);
|
|
var postData = JSON.stringify(request);
|
|
xmlhttp.setRequestHeader("Content-Type", "application/json");
|
|
xmlhttp.send(postData);
|
|
|
|
xmlhttp.onreadystatechange = function()
|
|
{
|
|
if (xmlhttp.readyState == 4) {
|
|
if (xmlhttp.status == 409) {
|
|
_overdrive.settings.sessionID = xmlhttp.getResponseHeader("X-Transmission-Session-Id");
|
|
_overdrive.ui.wantedBoxClick(event);
|
|
} else if (xmlhttp.status == 200) {
|
|
var response = JSON.parse(xmlhttp.responseText);
|
|
if (response.result != "success")
|
|
alert("wantedBoxClick() failed: " + response.result);
|
|
else
|
|
_overdrive.data.getEverything();
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
// Window close button click handler
|
|
_overdrive.ui.windowCloseClick = function(event)
|
|
{
|
|
event.currentTarget.parentNode.parentNode.style.display = "none";
|
|
};
|
|
|
|
// Titlebar mousedown handler
|
|
_overdrive.ui.windowTitleMouseDown = function(event)
|
|
{
|
|
_overdrive.ui.activeWindow = event.currentTarget.parentNode;
|
|
_overdrive.ui.windowDrag = true;
|
|
event.preventDefault();
|
|
};
|
|
|
|
// Stuff to do when window is finished loading
|
|
_overdrive.onLoad = function()
|
|
{
|
|
_overdrive.ui.lastHeight = window.innerHeight;
|
|
_overdrive.ui.lastWidth = window.innerWidth;
|
|
|
|
// Load some values from CSS sheet
|
|
var cssSheet = null;
|
|
for (var i = 0; i < document.styleSheets.length; i++) {
|
|
if (document.styleSheets[i].href.indexOf("overdrive.css") != -1) {
|
|
cssSheet = document.styleSheets[i];
|
|
break;
|
|
}
|
|
}
|
|
if (cssSheet != null) {
|
|
for (var i = 0; i < cssSheet.cssRules.length; i++) {
|
|
if (cssSheet.cssRules[i].selectorText == "#overdrive") {
|
|
_overdrive.ui.fontColor = cssSheet.cssRules[i].style.color;
|
|
_overdrive.ui.fontSize = cssSheet.cssRules[i].style.fontSize;
|
|
_overdrive.ui.fontFamily = cssSheet.cssRules[i].style.fontFamily;
|
|
} else if (cssSheet.cssRules[i].selectorText == "#overdrive-progress-detail") {
|
|
_overdrive.ui.canvasColor = cssSheet.cssRules[i].style.color;
|
|
} else if (cssSheet.cssRules[i].selectorText == "#overdrive-tab-contents") {
|
|
var margin = cssSheet.cssRules[i].style.marginBottom.slice(0, cssSheet.cssRules[i].style.marginBottom.indexOf("px"));
|
|
_overdrive.ui.detailsMargin = Number(margin);
|
|
|
|
var padding = cssSheet.cssRules[i].style.padding.slice(0, cssSheet.cssRules[i].style.padding.indexOf("px"));
|
|
_overdrive.ui.detailsPadding = Number(padding) * 2;
|
|
} else if (cssSheet.cssRules[i].selectorText == "#overdrive-torrent-list") {
|
|
var border = cssSheet.cssRules[i].style.border.slice(0, cssSheet.cssRules[i].style.border.indexOf("px"));
|
|
_overdrive.ui.listBorder = Number(border) * 2;
|
|
|
|
var margin = cssSheet.cssRules[i].style.margin.slice(0, cssSheet.cssRules[i].style.margin.indexOf("px"));
|
|
_overdrive.ui.listMargin = Number(margin) * 2;
|
|
} else if (cssSheet.cssRules[i].selectorText == ".overdrive-table-header div") {
|
|
var padding = cssSheet.cssRules[i].style.paddingLeft.slice(0, cssSheet.cssRules[i].style.paddingLeft.indexOf("px"));
|
|
_overdrive.ui.tableCellPadding = Number(padding) * 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Attempt to load stored UI settings from localStorage
|
|
_overdrive.settings.loadSettings();
|
|
|
|
// Attach event handlers
|
|
document.getElementById("overdrive-torrent-list").onmousedown = _overdrive.ui.listClick;
|
|
document.getElementById("overdrive-torrent-list").onscroll = _overdrive.ui.listScroll;
|
|
document.getElementById("overdrive-split-separator").onmousedown = function(event)
|
|
{
|
|
_overdrive.ui.sideResize = true;
|
|
event.preventDefault();
|
|
};
|
|
document.getElementById("overdrive-vert-separator").onmousedown = function(event)
|
|
{
|
|
_overdrive.ui.vertResize = true;
|
|
event.preventDefault();
|
|
};
|
|
document.getElementById("overdrive").onmouseup = function()
|
|
{
|
|
_overdrive.ui.sideResize = false;
|
|
_overdrive.ui.vertResize = false;
|
|
_overdrive.ui.windowDrag = false;
|
|
};
|
|
document.getElementById("overdrive").onmousemove = _overdrive.ui.mouseMove;
|
|
document.getElementById("overdrive").onkeydown = _overdrive.ui.keyHandler;
|
|
|
|
// Attach click handlers
|
|
document.getElementById("overdrive-add-button").onclick = _overdrive.ui.addClick;
|
|
document.getElementById("overdrive-add-cancel").onclick = _overdrive.ui.addCancelClick;
|
|
document.getElementById("overdrive-add-upload").onclick = _overdrive.ui.addUploadClick;
|
|
document.getElementById("overdrive-pause-button").onclick = _overdrive.ui.pauseClick;
|
|
document.getElementById("overdrive-resume-button").onclick = _overdrive.ui.resumeClick;
|
|
document.getElementById("overdrive-delete-button").onclick = _overdrive.ui.deleteClick;
|
|
document.getElementById("overdrive-delete-cancel").onclick = _overdrive.ui.deleteCancelClick;
|
|
document.getElementById("overdrive-delete-confirm").onclick = _overdrive.ui.deleteConfirmClick;
|
|
document.getElementById("overdrive-alt-button").onclick = _overdrive.ui.altClick;
|
|
|
|
var closeButtons = document.getElementsByClassName("overdrive-window-close");
|
|
for (var i = 0; i < closeButtons.length; i++)
|
|
closeButtons[i].onclick = _overdrive.ui.windowCloseClick;
|
|
|
|
var titleBars = document.getElementsByClassName("overdrive-window-titlebar");
|
|
for (var i = 0; i < titleBars.length; i++)
|
|
titleBars[i].onmousedown = _overdrive.ui.windowTitleMouseDown;
|
|
|
|
var stateLabels = document.getElementsByClassName("overdrive-state");
|
|
for (var i = 0; i < stateLabels.length; i++)
|
|
stateLabels[i].onmousedown = _overdrive.ui.stateClick;
|
|
|
|
var tabs = document.getElementsByClassName("overdrive-tab");
|
|
for (var i = 0; i < tabs.length; i++)
|
|
tabs[i].onmousedown = _overdrive.ui.tabClick;
|
|
|
|
document.getElementById("overdrive-status-table").onscroll = _overdrive.ui.statusTableScroll;
|
|
|
|
// UI adjustments
|
|
document.getElementById("overdrive-torrent-list-body").style.paddingTop = document.getElementById("overdrive-torrent-list-header").offsetHeight + "px";
|
|
|
|
var floatMenus = document.getElementsByClassName("overdrive-window");
|
|
for (var i = 0; i < floatMenus.length; i++) {
|
|
floatMenus[i].style.left = ((window.innerWidth / 2) - (floatMenus[i].offsetWidth / 2)) + "px";
|
|
floatMenus[i].style.top = ((window.innerHeight / 2) - (floatMenus[i].offsetHeight / 2)) + "px";
|
|
floatMenus[i].style.display = "none";
|
|
floatMenus[i].style.opacity = 1.0;
|
|
}
|
|
|
|
var details = document.getElementById("overdrive-tab-contents");
|
|
var diff = window.innerHeight - document.getElementById("overdrive").clientHeight;
|
|
details.style.height = ((details.clientHeight + diff) - (_overdrive.ui.detailsPadding + _overdrive.ui.detailsMargin)) + "px";
|
|
|
|
// Start communicating with server
|
|
window.setInterval(_overdrive.data.getEverything, _overdrive.settings.refreshRate);
|
|
};
|
|
|
|
// Attach onLoad handler
|
|
if (window.addEventListener) {
|
|
window.addEventListener("load", _overdrive.onLoad, false);
|
|
window.addEventListener("resize", _overdrive.ui.resize, false);
|
|
window.addEventListener("unload", _overdrive.settings.saveSettings, false);
|
|
}
|
|
else if (window.attachEvent) {
|
|
window.attachEvent("onload", _overdrive.onLoad);
|
|
window.attachEvent("onresize", _overdrive.ui.resize);
|
|
window.attachEvent("onunload", _overdrive.settings.saveSettings);
|
|
}
|