// ==UserScript==
// @name Nyaa.se Batch downloader
// @namespace Autodownload
// @author Victorique
// @description Batch download torrents from nyaa.se
// @include http://www.nyaa.se/?page=search&cats=*&filter=*&term=*&user=*
// @include http://www.nyaa.se/?page=search&filter=*&term=*&user=*
// @include http://www.nyaa.se/?page=search&term=*&user=*
// @version 4.1.3
// @license MIT
// @run-at document-start
// @grant none
// @require https://code.jquery.com/jquery-2.1.4.min.js
// ==/UserScript==
/*
var e = document.createElement("script");
e.src = 'http://localhost/userScripts/AutoDownloader.user.js';
e.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(e);
*/
"use strict";
/* OBJECT CREATION START */
var Episode = (function () {
/**
* An Episode represents an table row in the current page
* @param {Number} res The resolution used for this episode
* @param {String} downloadLink The download link for this episode
* @param {Number} seeds The seed count for this episode
* @param {Number} leechers The leech count for this episode
* @param {String} uid The ID of this episode
* @param {Number} resides The page that this Episode resides in
* @returns {Object} the proto of itself
*/
function Episode(res, downloadLink, seeds, leechers, uid, resides) {
if (typeof res !== "number") {
throw "res must be a number";
}
if (typeof downloadLink !== "string") {
throw "downloadLink must be a string";
}
if (typeof seeds !== "number") {
throw "seeds must be a number";
}
if (typeof leechers !== "number") {
throw "leechers must be a number";
}
if (typeof uid !== "string") {
throw "uid must be a string";
}
if (typeof resides !== "number") {
throw "resides must be a number";
}
var _res = res;
var _downloadLink = downloadLink;
var _seeds = seeds;
var _leechers = leechers;
var _uid = uid;
var _resides = resides;
this.getRes = function () {
return _res;
};
this.getDownloadLink = function () {
return _downloadLink;
};
this.getSeeds = function () {
return _seeds;
};
this.getLeechers = function () {
return _leechers;
};
this.getUid = function () {
return _uid;
};
this.getResides = function () {
return _resides;
};
return this;
}
Episode.prototype = {
constructor: Episode
}
return Episode;
}());
var Anime = (function () {
var currentAnime = null;
var currentSubber = null;
/**
* Array of Episode Objects
*/
var eps = [];
/**
* Set the current Anime name
* @param {String} anime The of the Anime
*/
var setCurrentAnime = function (anime) {
currentAnime = anime;
};
/**
* Set the name of the current subber
* @param {String} sub Name of the current subber
*/
var setCurrentSubber = function (sub) {
currentSubber = sub;
};
/**
* Get the current Subber
* @returns {String} The name of the Subber for this anime
*/
var getCurrentSubber = function () {
return currentSubber;
};
/**
* Get the current anime name
* @returns {String} Name of the anime
*/
var getCurrentAnime = function () {
return currentAnime;
};
/**
* Get the avrage seeds for a specified res
* @param {Number} res The res to get the avg seeds for
* @returns {Number} The avg seeds
*/
var avgSeedsForRes = function (res) {
if (typeof res !== "number") {
throw "res Must be an int";
}
var seedCount = 0;
if (getamountOfEpsFromRes(res) === 0) {
return 0;
}
for (var i = 0; i < eps.length; i++) {
var currentEp = eps[i];
if (currentEp.getRes() === res) {
seedCount += currentEp.getSeeds();
}
}
return Math.round(seedCount = seedCount / getamountOfEpsFromRes(res));
};
/**
* Get the avrage leechers for a specified res
* @param {Number} res The res to get the avg seeds for
* @returns {Number} The avg leechers
*/
var avgPeersForRes = function (res) {
if (typeof res !== "number") {
throw "res Must be an int";
}
var leechCount = 0;
if (getamountOfEpsFromRes(res) === 0) {
return 0;
}
for (var i = 0; i < eps.length; i++) {
var currentEp = eps[i];
if (currentEp.getRes() === res) {
leechCount += currentEp.getLeechers();
}
}
return Math.round(leechCount = leechCount / getamountOfEpsFromRes(res));
};
/**
* Get the total amount of eps for a res
* @param {Number} res res
* @returns {Number} The amount of eps for the res
*/
var getamountOfEpsFromRes = function (res) {
if (typeof res !== "number") {
throw "res must be of type 'number'";
}
return getEpsForRes(res).length;
};
var _isjQueryObject = function (obj) {
if (obj instanceof jQuery || 'jquery' in Object(obj)) {
return true;
} else {
return false;
}
};
/**
* Add Episodes to the array
* @param {Episode} ep The Anime object to add
*/
var addEps = function (ep) {
if (typeof ep !== "object" && !ep instanceof Episode) {
throw "addEps must take an Episode object";
}
eps.push(ep);
};
/**
* Add an array of Episode object to the Anime object
* @param {Array} episode Array of Episode objects to add
*/
var addAllEps = function (episode) {
for (var i = 0; i < episode.length; i++) {
var currEp = episode[i];
if (typeof currEp !== "object" && !currEp instanceof Episode) {
throw "addEps must take an Episode object";
}
eps.push(currEp);
}
};
/**
* Get the Anime objects for a specified res
* @param {Number} res res to use
* @returns {Episode} Array of Episodes that match the specified res
*/
var getEpsForRes = function (res) {
if (typeof res !== "number") {
throw "res Must be an int";
}
var arrayOfEps = [];
for (var i = 0; i < eps.length; i++) {
var currentEp = eps[i];
if (currentEp.getRes() === res) {
arrayOfEps.push(currentEp);
}
}
return arrayOfEps;
};
/**
* Given a JQuery object that represents a "tr" of the table, this will return that Episode's UID
* @param {Object} obj The Jquery representation of a tr (table row)
* @returns {String} The UID of that Episode
*/
var getUidFromJqueryObject = function (obj) {
if (!_isjQueryObject(obj)) {
throw "Object must be of type 'Jquery'";
}
if (obj.is("tr")) {
var anchor = (function () {
var tableRows = obj.find("td.tlistdownload > a");
if (tableRows.length > 1) {
throw "Object must be unique";
}
return _getUidFromAnchor(tableRows.get(0))
}());
} else {
return null;
}
return anchor;
};
/**
* Get the Episode from a given anchor tag
* @param {Object} anchor Jquery or pure JS anchor dom element
* @returns {Episode} The eipside that matches the Anchor
*/
var getEpisodeFromAnchor = function (anchor) {
var link = (function () {
if (_isjQueryObject(anchor)) {
return anchor.get(0);
}
return anchor;
}());
var uid = _getUidFromAnchor(link);
return getEpisodeFromUid(uid);
};
/**
* Get the Episode object given a UID
* @param {String} uid The Episode UID
* @returns {Episode} The Episode that matches the UID
*/
var getEpisodeFromUid = function (uid) {
if (typeof uid !== "string") {
throw "uid must be of type String";
}
for (var i = 0; i < eps.length; i++) {
var currentEp = eps[i];
if (currentEp.getUid() === uid) {
return currentEp;
}
}
return null;
};
/**
* Get an array of Episodes that from the page that it came from
* @param {Number} resides The page where the Episode originated from
* @param {Boolean} exclude Match this page only, or exculde this page and return all other objects. if true, will return all Episodes that are not of the passed in page
* @returns {Episode} Array of Episodes
*/
var getEpisodesFromResidence = function (resides, exclude) {
if (typeof resides !== "number") {
throw "resides must be a number";
}
var arrayOfEps = [];
for (var i = 0; i < eps.length; i++) {
var currentEp = eps[i];
if (exclude === true) {
if (currentEp.getResides() !== resides) {
arrayOfEps.push(currentEp);
}
} else {
if (currentEp.getResides() === resides) {
arrayOfEps.push(currentEp);
}
}
}
return arrayOfEps;
};
/**
* Get the UID from an anchor tag
* @param {Object} anchor Dom element of an Anchor
* @returns {String} The UID
*/
var _getUidFromAnchor = function (anchor) {
return anchor.href.split("=").pop();
};
/**
* Remove an object from an array
* @param {Array} arr Array to search in
* @param {Object} obj Object to remove
*/
var _removeObjectFromArray = function (arr, obj) {
var i = arr.length;
while (i--) {
if (arr[i] === obj) {
arr.splice(i, 1);
}
}
}
/**
* Get an array of all the pages avalible in the Anime (tables)
* @returns {Array} Array of URLS
*/
var getPageUrls = function () {
var urls = [];
$.each($('div.pages').filter(function (i) {
return i === 0;
}).find('a'), function (k, v) {
urls.push(this.href);
});
return urls;
};
/**
* Remove an episode from the Episode array based on UI
* @param {String} uid the UID
*/
var removeEpisodesFromUid = function (uid) {
var episodes = getEpisodeFromUid(uid);
for (var i = 0; i < episodes.length; i++) {
var currentEp = episodes[i];
_removeObjectFromArray(eps, currentEp);
}
};
/**
* Remove all episodes that match a page number
* @param {Number} resides The page number
* @param {Boolean} exclude if true, this will remove all Episode objects that do not match the passed in page number. if false, removes all episodes that match the passed in page number
*/
var removeEpisodesFromResidence = function (resides, exclude) {
if (typeof exclude !== "boolean") {
throw "excluse must be true or false";
}
var episodes = getEpisodesFromResidence(resides, exclude);
for (var i = 0; i < episodes.length; i++) {
var currentEp = episodes[i];
_removeObjectFromArray(eps, currentEp);
}
};
var getAmountOfEps = function () {
return eps.length;
};
return {
setCurrentAnime: setCurrentAnime,
getCurrentAnime: getCurrentAnime,
addEps: addEps,
getEpsForRes: getEpsForRes,
getamountOfEpsFromRes: getamountOfEpsFromRes,
setCurrentSubber: setCurrentSubber,
getCurrentSubber: getCurrentSubber,
avgSeedsForRes: avgSeedsForRes,
getUidFromJqueryObject: getUidFromJqueryObject,
getEpisodeFromUid: getEpisodeFromUid,
getEpisodeFromAnchor: getEpisodeFromAnchor,
getPageUrls: getPageUrls,
addAllEps: addAllEps,
getEpisodesFromResidence: getEpisodesFromResidence,
removeEpisodesFromUid: removeEpisodesFromUid,
removeEpisodesFromResidence: removeEpisodesFromResidence,
avgPeersForRes: avgPeersForRes,
getAmountOfEps: getAmountOfEps
};
}());
/** Utility functions ***/
var Utils = (function () {
/**
* Display a message to the use (built in alert)
* @param {String} message Message to show
* @param {Boolean} confirmMsg If true, message will be a confirm alert (yes or no)
* @returns {Boolean} Returns true if confirmMsg is false, else returns true or false depending on the user selection
*/
var displayMessage = function (message, confirmMsg) {
if (typeof confirmMsg === "boolean") {
if (confirmMsg === true) {
return confirm(message);
}
}
alert(message);
return true;
};
/**
* Disable the given button
* @param {Object} button Jquery object of the button
*/
var disableButton = function (button) {
button.prop('disabled', true);
};
/**
* Enable the given button
* @param {Object} button Jquery object of the button
*/
var enableButton = function (button) {
button.prop('disabled', false);
};
/**
* Do the downloads
* @param {Object} event The event to decide if it is a download all or a downlaod selection (to make this method more abstract)
*/
var doDownloads = function (event) {
var type = $(event.target).data("type");
var amountOfAnime;
var collectionOfAnime;
var userSelect;
var _minSeeds = Options.Seeds.minSeeds === -1 ? 0 : Options.Seeds.minSeeds;
if (type === "downloadAll") {
var selectedRes = parseInt($("#downloadRes").val());
amountOfAnime = Anime.getamountOfEpsFromRes(selectedRes);
collectionOfAnime = Anime.getEpsForRes(selectedRes);
userSelect = displayMessage("You are about to download " + amountOfAnime + " eps.\n\
This will cause " + amountOfAnime + " download pop-ups\nAre you sure you want to continue?\nIf there are a lot of eps, your browser might stop responding for a while.\
This is normal\nIf you are on Google Chrome, it will ask you to allow multiple-downloads\n\nYour min seeds restriction is: " + _minSeeds + "\
This will not be reflected in this message download count, but all episodes with this restriction will be skipped", true);
} else if (type === "downloadSelected") {
amountOfAnime = $(".checkboxes:checked").length;
collectionOfAnime = [];
$.each($('.checkboxes:checked').prev('a'), function (k, v) {
var episode = Anime.getEpisodeFromAnchor(this);
collectionOfAnime.push(episode);
});
userSelect = displayMessage("You are about to download " + amountOfAnime + " items. if there are a lot of itmes, it might make your browser stop responding for a while This is normal\n\
Chrome will ask you to accept multiple downloads ", true);
} else {
throw "Unexpected Error";
}
if (userSelect === false) {
return;
}
for (var i = 0; i < collectionOfAnime.length; i++) {
var currentEp = collectionOfAnime[i];
if (_minSeedsSet() && type !== "downloadSelected") {
if (currentEp.getSeeds() < _minSeeds) {
continue;
}
}
var currentDownloadLink = currentEp.getDownloadLink();
var link = document.createElement("a");
link.download = "";
link.href = currentDownloadLink;
link.click();
}
};
/**
* Returns if the checkbox is checked
* @param {Object} checkbox The checkbox
* @returns {Boolean} If ehcked or not
*/
var checkBoxValid = function (checkbox) {
return checkbox.is(":checked");
};
var _minSeedsSet = function () {
return Options.Seeds.minSeeds !== -1 ? true : false;
//(typeof Options.Seeds.minSeeds !== "undefined") ? 0: Options.Seeds.minSeeds;
}
/**
* Build the download infomation table
* @returns {String} The html of the built table
*/
var buildTable = function () {
var html = "";
html += "<table style='width: 100%' id='info'>";
html += "<caption>Download infomation</caption>";
html += "<thead>";
html += "<tr>";
html += "<th>resolution</th>";
html += "<th>Episode count</th>";
html += "<th>Average seeds</th>";
html += "<th>Average leechers</th>";
html += "</tr>";
html += "</thead>";
html += "<tbody>";
html += "<tr>";
html += "<td>1080p</td>";
html += "<td>" + Anime.getamountOfEpsFromRes(1080) + "</td>";
html += "<td>" + Anime.avgSeedsForRes(1080) + "</td>";
html += "<td>" + Anime.avgPeersForRes(1080) + "</td>";
html += "</tr>";
html += "<tr>";
html += "<td>720p</td>";
html += "<td>" + Anime.getamountOfEpsFromRes(720) + "</td>";
html += "<td>" + Anime.avgSeedsForRes(720) + "</td>";
html += "<td>" + Anime.avgPeersForRes(720) + "</td>";
html += "</tr>";
html += "<tr>";
html += "<td>480p</td>";
html += "<td>" + Anime.getamountOfEpsFromRes(480) + "</td>";
html += "<td>" + Anime.avgSeedsForRes(480) + "</td>";
html += "<td>" + Anime.avgPeersForRes(480) + "</td>";
html += "</tr>";
html += "<tr>";
html += "<td>360p</td>";
html += "<td>" + Anime.getamountOfEpsFromRes(360) + "</td>";
html += "<td>" + Anime.avgSeedsForRes(360) + "</td>";
html += "<td>" + Anime.avgPeersForRes(360) + "</td>";
html += "</tr>";
html += "</tbody>";
html += "</table>";
return html;
};
/**
* Return the current page offset (what table page you are on)
* @returns {Number} The offset
*/
var getCurrentPageOffset = function () {
return parseInt((typeof QueryString.offset === "undefined") ? 1 : QueryString.offset);
};
/**
* Returns true of false if you can support HTML5 storeag
* @returns {Boolean}
*/
var html5StoreSupport = function () {
try {
return 'localStorage' in window && window['localStorage'] !== null;
} catch (e) {
return false;
}
};
var injectCss = function (css) {
if (_isUrl(css)) {
$("<link>").prop({
"type": "text/css",
"rel": "stylesheet"
}).attr("href", css).appendTo("head");
} else {
$("<style>").prop("type", "text/css").html(css).appendTo("head");
}
};
var _isUrl = function (url) {
var matcher = new RegExp(/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/);
return matcher.test(url);
};
return {
displayMessage: displayMessage,
disableButton: disableButton,
enableButton: enableButton,
doDownloads: doDownloads,
checkBoxValid: checkBoxValid,
buildTable: buildTable,
getCurrentPageOffset: getCurrentPageOffset,
html5StoreSupport: html5StoreSupport,
injectCss: injectCss
};
}());
var DataParser = (function () {
/**l
* Parses a table and returns an array of Episodes from it
* @param {Object} table Jquery representation of the anime table
* @returns {Episode} Array of Episodes
*/
var parseTable = function (table, currentPage) {
var trRow = table.find("img[src='http://files.nyaa.se/www-37.png']").closest("tr");
var eps = [];
$(trRow).filter(function (e) {
return ($(this).children('td:nth-child(2)').text().indexOf('1080p') > -1 || $(this).children('td:nth-child(2)').text().indexOf('1920x1080') > -1);
}).each(function (k, v) {
var currentDownloadLink = $(this).find('td:nth-child(3) >a').attr('href');
var seeds = (isNaN(parseInt($(this).find("td.tlistsn").text()))) ? 0 : parseInt($(this).find("td.tlistsn").text());
var leech = (isNaN(parseInt($(this).find("td.tlistln").text()))) ? 0 : parseInt($(this).find("td.tlistln").text());
var uid = Anime.getUidFromJqueryObject($(this));
eps.push(new Episode(1080, currentDownloadLink, seeds, leech, uid, currentPage));
});
$(trRow).filter(function (e) {
return ($(this).children("td:nth-child(2)").text().indexOf("720p") > -1 || $(this).children("td:nth-child(2)").text().indexOf("1280x720")) > -1;
}).each(function (k, v) {
var currentDownloadLink = $(this).find('td:nth-child(3) >a').attr('href');
var seeds = (isNaN(parseInt($(this).find("td.tlistsn").text()))) ? 0 : parseInt($(this).find("td.tlistsn").text());
var leech = (isNaN(parseInt($(this).find("td.tlistln").text()))) ? 0 : parseInt($(this).find("td.tlistln").text());
var uid = Anime.getUidFromJqueryObject($(this));
eps.push(new Episode(720, currentDownloadLink, seeds, leech, uid, currentPage));
});
$(trRow).filter(function (e) {
return ($(this).children("td:nth-child(2)").text().indexOf("480p") > -1 || $(this).children("td:nth-child(2)").text().indexOf("640x480") > -1);
}).each(function (k, v) {
var currentDownloadLink = $(this).find('td:nth-child(3) >a').attr('href');
var seeds = (isNaN(parseInt($(this).find("td.tlistsn").text()))) ? 0 : parseInt($(this).find("td.tlistsn").text());
var leech = (isNaN(parseInt($(this).find("td.tlistln").text()))) ? 0 : parseInt($(this).find("td.tlistln").text());
var uid = Anime.getUidFromJqueryObject($(this));
eps.push(new Episode(480, currentDownloadLink, seeds, leech, uid, currentPage));
});
$(trRow).filter(function (e) {
return ($(this).children("td:nth-child(2)").text().indexOf("360p") > -1 || $(this).children("td:nth-child(2)").text().indexOf("640×360") > -1);
}).each(function (k, v) {
var currentDownloadLink = $(this).find('td:nth-child(3) >a').attr('href');
var seeds = (isNaN(parseInt($(this).find("td.tlistsn").text()))) ? 0 : parseInt($(this).find("td.tlistsn").text());
var leech = (isNaN(parseInt($(this).find("td.tlistln").text()))) ? 0 : parseInt($(this).find("td.tlistln").text());
var uid = Anime.getUidFromJqueryObject($(this));
eps.push(new Episode(360, currentDownloadLink, seeds, leech, uid, currentPage));
});
return eps;
};
return {
parseTable: parseTable,
};
}());
var QueryString = function () {
var query_string = {};
var query = window.location.search.substring(1);
var vars = query.split('&');
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
if (typeof query_string[pair[0]] === 'undefined') {
query_string[pair[0]] = pair[1];
} else if (typeof query_string[pair[0]] === 'string') {
var arr = [
query_string[pair[0]],
pair[1]
];
query_string[pair[0]] = arr;
} else {
query_string[pair[0]].push(pair[1]);
}
}
return query_string;
}();
var Options = (function () {
var Seeds = {};
Object.defineProperty(Seeds, "minSeeds", {
enumerable: true,
set: function (seeds) {
if (typeof seeds !== "number") {
throw "seeds must be a number";
}
this._minSeeds = seeds;
if (Utils.html5StoreSupport() === true) { // also set it on the local DB
if (this._minSeeds === -1) {
Localstore.removeMinSeedsFromStore();
} else {
Localstore.setMinSeedsFromStore(this._minSeeds);
}
}
},
get: function () {
return typeof this._minSeeds === "undefined" ? -1 : this._minSeeds;
}
});
return {
Seeds: Seeds
}
}());
//Local storeage object
var Localstore = {
getMinSeedsFromStore: function () {
return localStorage.getItem("minSeeds");
},
setMinSeedsFromStore: function (seeds) {
localStorage.setItem('minSeeds', seeds);
},
removeMinSeedsFromStore: function () {
localStorage.removeItem("minSeeds");
}
};
// Download fix for firefox
HTMLElement.prototype.click = function () {
var evt = this.ownerDocument.createEvent('MouseEvents');
evt.initMouseEvent('click', true, true, this.ownerDocument.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
this.dispatchEvent(evt);
};
/* OBJECT CREATION END */
$(document).ready(function () {
init(); // init the pannel and set up objects and listeners
if (Utils.checkBoxValid($(".checkboxes"))) { // TODO: Refactor this statement!
Utils.enableButton($("#downloadCustomButton"));
} else {
Utils.disableButton($("#downloadCustomButton"));
}
});
function init() {
var doDownload = true;
setAnimeObj();
buildUi();
bindListeners();
if (Utils.html5StoreSupport()) {
setOptionsFromLocalStor();
}
function setAnimeObj() {
// Set currentAnime
if (QueryString.term !== "") {
Anime.setCurrentAnime(decodeURIComponent(QueryString.term).split("+").join(" "));
} else {
Anime.setCurrentAnime("Unknown");
}
// set subber
Anime.setCurrentSubber($(".notice > a > span").html());
// Set eps
var eps = DataParser.parseTable($("table.tlist"), Utils.getCurrentPageOffset());
Anime.addAllEps(eps);
}
function buildUi() {
makeStyles();
buildPanel();
makeCheckBoxes();
function makeStyles() {
var styles = "";
styles += ".panel{background-color: #fff; border: 1px solid transparent; border-radius: 4px; box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); margin-bottom: 20px;}";
styles += ".panel-success {border-color: #d6e9c6;}";
styles += ".panel-heading{ border-bottom: 1px solid transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; padding: 4px 15px; text-align:center}";
styles += ".panel-success > .panel-heading {background-color: #dff0d8; border-color: #d6e9c6; color: #3c763d;}";
styles += ".panel-success > .panel-footer + .panel-collapse > .panel-body {border-bottom-color: #d6e9c6;}";
styles += ".panel-footer {background-color: #f5f5f5; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-top: 1px solid #ddd; padding: 10px 15px;}";
styles += ".panel-title {color: inherit; margin-bottom: 0; margin-top: 0; padding: 6px;}";
styles += ".panel-body {padding: 15px;}";
styles += ".avgSeeds{floar:left; padding-right:10px; color:#3c763d;}";
styles += ".checkboxes{left:1px; margin:0; padding:0; position: relative; top: 1px;}";
styles += "#info, #info th, #info td {border: 1px solid black;border-collapse: collapse;}";
styles += "#info th, #info td {padding: 5px;text-align: left;}";
styles += "label[for='MinSeeds']{ display: block; margin-top: 10px;}";
styles += "#SaveMinSeeds{margin-left:5px;}"
styles += "#downloadCustomButton{float:right;}";
Utils.injectCss(styles);
}
function buildPanel() {
var html = "";
html += '<div class="panel panel-success" style="margin-left: 9px; margin-top: 19px; width: 851px;">';
html += '<div class="panel-heading">';
html += '<h3 id="panel-title" class="panel-title"></h3>';
html += "</div>";
html += '<div class="panel-body" id="pannelContent"></div>';
html += '<div class="panel-footer" id="panelFooter">';
html += '</div>';
html += '</div>';
$(".content > .notice").after(html);
buildPanelContent();
function buildPanelContent() {
var html = "";
html += "<div>";
$("#panel-title").html("<span> Download \"" + Anime.getCurrentAnime() + " (" + Anime.getCurrentSubber() + ")\"</span>");
if (Anime.getAmountOfEps() === 0) {
html += "<span> No translated anime found or error occured</span>";
html += "</div>";
$("#pannelContent").html(html);
doDownload = false;
return;
}
html += "<span>Pick a resolution: </span>";
html += "<select style=\"margin-right:5px;\" id=\"downloadRes\">";
if (Anime.getamountOfEpsFromRes(1080) >= 1) {
html += "<option value=\"1080\">1080p</option>";
}
if (Anime.getamountOfEpsFromRes(720) >= 1) {
html += "<option value=\"720\">720p</option>";
}
if (Anime.getamountOfEpsFromRes(480) >= 1) {
html += "<option value=\"480\">480p</option>";
}
if (Anime.getamountOfEpsFromRes(360) >= 1) {
html += "<option value=\"360\">360p</option>";
}
html += "</select>";
html += "<button type=\"button\" data-type='downloadAll' id=\"downloadAll\">Download all</button>";
html += "<button type='button' id='downloadCustomButton' data-type='downloadSelected' >download your selected items</button>";
html += "</div>";
html += "<div id='options'>";
html += "<label for='crossPage'> include Cross pages</label>";
html += "<input type='checkbox' id='crossPage' /> ";
html += "<label for='MinSeeds'>Minimum seeders:</label>";
html += "<input type='number' min='0' id='MinSeeds' title='Any episode that is below this limit will be excluded from the download but not the infomation table (coming soon).'/>";
html += "<button type='button' id='SaveMinSeeds'>Save</button>";
html += "</div>";
html += "<div id='tableInfo'>";
html += Utils.buildTable();
html += "</div>";
$("#pannelContent").html(html);
}
}
function makeCheckBoxes() {
$(".tlistdownload > a").after("<input class='checkboxes' type='checkbox'/>");
}
}
function bindListeners() {
$("#downloadAll").on("click", function (e) {
if (doDownload === true) {
Utils.doDownloads(e);
}
});
$("#downloadCustomButton").on("click", function (e) {
if (doDownload === true) {
Utils.doDownloads(e);
}
});
$(".checkboxes").on("click", function (e) {
if (Utils.checkBoxValid($(".checkboxes"))) {
Utils.enableButton($("#downloadCustomButton"));
} else {
Utils.disableButton($("#downloadCustomButton"));
}
});
$("#crossPage").on("click", function (e) {
if (Utils.checkBoxValid($("#crossPage"))) {
$("#tableInfo").html("<p>Please wait while we parse each page...</p>");
$("#crossPage").prop("disabled", true);
Anime.getPageUrls().reduce(function (prev, cur, index) {
return prev.then(function (data) {
return $.ajax(cur).then(function (data) {
var currentPage = cur.split("=").pop();
if (cur.indexOf("offset") === -1) {
currentPage = 1;
}
var table = $(data).find("table.tlist");
Anime.addAllEps(DataParser.parseTable(table, parseInt(currentPage)));
$("#tableInfo").append("<div>Page " + currentPage + " Done </div>")
});
})
}, $().promise()).done(function () {
$("#tableInfo").html(Utils.buildTable());
$("#crossPage").prop("disabled", false);
});
} else { // when un-chekced, clear the Episodes of all eps that are not of the current page
$("#tableInfo").html("<p>Please wait while we re-calculate the Episodes</p>");
var currentPage = Utils.getCurrentPageOffset();
Anime.removeEpisodesFromResidence(currentPage, true);
$("#tableInfo").html(Utils.buildTable());
}
});
$("#SaveMinSeeds").on("click", function (e) {
if (parseInt($("#MinSeeds").val()) < 0) {
alert("number cannot be negative");
return;
}
var value = parseInt($("#MinSeeds").val() === "" ? -1 : $("#MinSeeds").val());
Options.Seeds.minSeeds = value;
if (value === -1) {
alert("Minimum seeds have been cleared");
} else {
alert("Minimum seeds now set to: " + value);
}
});
}
function setOptionsFromLocalStor() {
// Min seeds
if (Localstore.getMinSeedsFromStore() !== null) {
var minSeeds = parseInt(Localstore.getMinSeedsFromStore());
Options.Seeds.minSeeds = minSeeds;
$("#MinSeeds").val(minSeeds);
}
}
}