您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
Torrentz.eu: Add IMDB ratings, download links, movie plot/actors, and other goodies. Also features an light built-in serie tracker. Torrentz gets so much simpler and efficient! Demo video here: http://www.youtube.com/watch?v=1QyuIDw0CIw&feature=youtu.be
当前为
// ==UserScript== // @name Torrentz : The Bobcat add-on // @namespace http://torrentzBobCat // @homepage http://www.youtube.com/watch?v=1QyuIDw0CIw&feature=youtu.be // @description Torrentz.eu: Add IMDB ratings, download links, movie plot/actors, and other goodies. Also features an light built-in serie tracker. Torrentz gets so much simpler and efficient! Demo video here: http://www.youtube.com/watch?v=1QyuIDw0CIw&feature=youtu.be // @author CoolMatt // @version 1.3.7 // @grant none // @include *://torrentz.* // @match *://torrentz.com/* // @match *://torrentz.eu/* // ==/UserScript== // @date 19 Jun 2013 // @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html //Define the namespace var Torrentz = Torrentz || {}; Torrentz.GM = {}; Torrentz.GM.BobCatTorrentz = {}; Torrentz.GM.BobCatTorrentz = { PageCache_movieInfo: {}, //Store info about movies of the page PageCache_lk_id_info: {}, //Lookup table - as several torrentz can point at the same movie info start: function () { initCss(); this.addBadgeAndButtons(); $("div.cloud").hide(); var loginStore = Enbalaba.GetLocalStore("moviesInfo"), loginData = loginStore.get(), that = this, results; //Calculate cache size and clear it if too big this.checkCacheSize(loginStore); //Get rid of this incredibly annoying & ridiculous advertising banner $("body>iframe:first").hide(); //Start processing of the rows results = $(".results"); results.find("h3:first").append("<span>| </span><b title='IMDB Rating. Brought to you by the Torrentz Dominion Plugin'>Rating</b>"); results.children("dl").each(function (index) { that.processRow($(this), loginData, false); }); results.find("span.downloadLink").click(function () { $(this).replaceWith("<div class='fleft bobcatStamp' style='width:80px;height:25px;position:relative;top:-4px'></div>"); downloadTorrent($(this).attr("data-torrentid")); }); //Add events for when the row is clicked results.find("dt").click(function () { var dt = $(this), text, divDesc = dt.find(".movieDesc"), div, lk, aElement; if (divDesc.length == 0) { //First time the user clicks here aElement = dt.children("a:first"); if (aElement.length == 0) return; var id = aElement.attr("href").substr(1).toUpperCase(), info = null; if (!id) return; //Retrieve info from cache if (that.PageCache_lk_id_info[id]) { info = that.PageCache_movieInfo[that.PageCache_lk_id_info[id]]; } if (info) { // text = "<div class='plot'><b>Plot</b>: " + info.Plot + "</div><div class='actorsInfo'> <b>Actors</b>: " + info.Actors + "</div>"; } else { //No info > display the title text = aElement.attr("title"); } divDesc = $("<div class='movieDesc'>" + text + "</div>"); div = $("<div class='divQuality'></div>"); lk = $("<div class='hyperlink fleft'>See user comments</div>"); lk.hover(function (e) { if ($(this).data('processed')) return; that.getQuality($(this.parentNode), aElement.attr("href")); e.stopPropagation(); $(this).hide(); $(this).data('processed', true); }); div.append(lk).append($("<img class='spinner fleft'></div><div class='qualityComments'><div/>").hide()); //Add get Quality link and spinner image divDesc.append(div).hide(); dt.append(divDesc); } if (divDesc.is(":hidden")) { divDesc.children().hide(); divDesc.slideDown(200, function () { divDesc.children().show(); }); //dt.children(".expandCollapse").removeClass("expand").addClass("collapse"); dt.children(".expand").addClass("collapse"); } else { divDesc.slideUp(); dt.children(".expand").removeClass("collapse"); } }); // Once a day, the serie tracker check if there are new episodes available this.checkForNewEpisodes(); } , processRow: function (row, loginData, isIFrameDownload) { if (!row) return; var tags = null, name, lk = row.find("dt>a"); if (lk.length > 0) { var id = lk.attr("href").substr(1).toUpperCase(), //Get id from href info = lk.parent().text(), index = info.indexOf('\u00BB'), //Look for the utf-8 character >> in the row rightCol = row.find("dd"); rightCol.css("width", "400px"); row.find("dt").css("width", "540px"); if (index > -1) { tags = info.substr(index + 1); name = info.substr(0, index); } lk.attr("title", tags ? "Tags: " + tags : info).parent().html(lk); //Remove info to make some room //lk.after("<span class='moreLk'>more</span>"); var type = this.getType(name, tags); if (this.isTVSerie(name)) { type = "tv"; //extra verification as sometimes a tv serie is not tagged as such } if (type == "movie") { if (!loginData) return; lk.css('color', '#3F14FF'); var yearIndex = name.search(/\s[0-9]{4}\s/); //Year is mandatory if (yearIndex != -1) { var year = name.substr(yearIndex + 1, 4); name = name.substr(0, yearIndex); //console.log(name + ":" + year); info = loginData[(name + year).toLowerCase()]; //Search in cache if (info) { this.PageCache_movieInfo[(name + year).toLowerCase()] = info; this.PageCache_lk_id_info[id] = (name + year).toLowerCase(); lk.text(name + " " + year); rightCol.append($("<a class='rateBox' " + (info.ImdbID && info.ImdbID != "" ? "target='_blank' href='http://www.imdb.com/title/" + info.ImdbID + "'" : "") + " >" + info.imdbRating + "</a>")); } else { this.searchIMDBinfo(name, year, lk, rightCol); } } } else if (type == "tv") { lk.css('color', 'Black' /*'#47D4FF'*/); } else { lk.css('color', '#555'); } //Add link //if (isIFrameDownload == true) { rightCol.prepend("<span class='downloadLink hyperlink' data-torrentid='" + id + "'>Download</span>"); //rightCol.prepend("<div class='downloadIcon fleft' data-torrentid='" + id + "'></div>"); lk.parent().prepend("<div class='expand fleft'></div>"); } //this.attachRowEvent(row); //row.find("span.downloadLink").text("download"); } , getType: function (name, tags) { if (tags.indexOf("movies") > -1) return "movie"; else if (tags.indexOf("tv") > -1) return "tv"; else if (tags.indexOf("games") > -1) return "game"; } /*As sometimes the tv serie is not tagged as such. This test will help catch those ones*/ , isTVSerie: function (fullName) { return ( new RegExp(/[sS][0-9]+[eE][0-9]+/).test(fullName) || new RegExp(/[0-9]+[x][0-9]+/).test(fullName) || new RegExp(/season[\s]?[0-9]{1,2}[\s]/i).test(fullName) ); } /* * */ , searchIMDBinfo: function (name, year, link, rightCol, isRetry) { //console.log("encodeURI('http://www.imdbapi.com/?t=" + name + "')"); var url = encodeURI("http://www.imdbapi.com/?t=" + name), that = this; $("<span></span>").css("display", "none").load(url, function (data) { var obj = $.parseJSON(data); if (obj) { if (obj.imdbRating) { var loginStore = Enbalaba.GetLocalStore("moviesInfo") , loginData = loginStore.get(); if (loginData) { var refName = (name + year).toLowerCase(); that.PageCache_movieInfo[refName] = { imdbRating: obj.imdbRating, Plot: obj.Plot, Actors: obj.Actors, ImdbID: obj.imdbID }; that.PageCache_lk_id_info[link.attr("href").substr(1).toUpperCase()] = refName; loginData[refName] = { imdbRating: obj.imdbRating, Plot: obj.Plot, Actors: obj.Actors, ImdbID: obj.imdbID }; loginStore.set(loginData); } rightCol.append($("<a class='rateBox' " + (obj.imdbID && obj.imdbID != "" ? "target='_blank' href='http://www.imdb.com/title/" + obj.imdbID + "'" : "") + " >" + obj.imdbRating + "</a>")); //rightCol.prepend($("<input type='text' disabled='disabled' class='rateBox' value='" + obj.imdbRating + "'></input>")); //tbMark.val(obj.imdbRating); //if (obj.Plot) link.attr("title", obj.Plot).data("MovieInfo", { imdbRating: obj.imdbRating, Plot: obj.Plot, Actors: obj.Actors }); } else if (obj.Response == "False"/* && obj.Error.indexOf("Movie not found") != -1*/) { if (isRetry != true) { //Tries a second search var name2 = name.replace(/thats/gi, "that's").replace(/it's/gi, "its").replace(/spiderman/i, "spider man").replace(/extended$/i, ""); if (name2 != name) { that.searchIMDBinfo(name2, year, link, rightCol, true); return; } } console.info(name + ": " + obj.Error); //rightCol.prepend($("<input type='text' disabled='disabled' class='rateBox' value='?'></input>")); } } }); return; } , tempID: 0 , getQuality: function ($qualityDiv, url) { url = "http://torrentz.eu" + url; //console.info(url); $qualityDiv.find(".spinner").show(); var id = "divComment" + (this.tempID++); $("<div style='display:none' id='" + id + "'></div>").load(url, function (data) { var comments = $(data).find("div.comment .com"), qualityComments = []; for (var i = 0, comment; i < comments.length; i++) { comment = $(comments[i]).text(); if (comment.length > 400) comment = comment.substr(0, 400) + " (...)"; qualityComments.push(comment); } $qualityDiv.find(".spinner").hide(); $qualityDiv.find(".qualityComments").show().html("<b>User comment:</b><br/>" + qualityComments.join("<br/>")); $(id).empty(); //free memory of the temporary div }); } /* * Calculate cache size and clear it if too big */ , checkCacheSize: function (loginStore) { var cacheSize, k, that = this, loginData = loginStore.get(); try { //Works in all recent browsers cacheSize = Object.keys(loginData).length; } catch (err) { cacheSize = 0; for (k in loginData) { if (loginData.hasOwnProperty(k)) cacheSize++; } } console.log("Bobcat - Cache size:" + cacheSize); if (cacheSize > 150) { //Clear the cache from time to time loginStore.set({}); console.info("Bobcat - Movie cache cleared"); } } /* * Add badges and buttons */ , addBadgeAndButtons: function () { //Add bobcat badge in the top banner $("div.top").append("<div id='bobcatLogoContainer' class='bobcatLogo'><a href='http://www.youtube.com/watch?v=1QyuIDw0CIw&feature=youtu.be'>with the Bobcat add-on</a></div>"); //Add serie tracker button var btST = $("<button type='button' id='btSerieTracker' class='bcButton bobcatStamp'>Serie Tracker</button>"), that = this; btST.click(function () { that.onclick_btSerieTracker(); }); $("div.results h2").append(btST); //this.onclick_btSerieTracker(); //~~ Uncomment when developping serie tracker } //--------------------- //-----SERIE TRACKER--- //--------------------- , _ddSeasonHTML: "" , _ddEpisodeHTML: "" , onclick_btSerieTracker: function () { if (!this.SerieTrackerMode) { $("div.results h3").nextAll().hide(); $("div.recent").hide(); $("#serieContainer").show(); $("#btSerieTracker").text("Return to List"); if (this.SerieTrackerMode == null) { //init serie tracker var serieTrakerLastCheckedStore = Enbalaba.GetLocalStore("serieTrackerLastCheck") , serieTrakerLastChecked = serieTrakerLastCheckedStore.get(); serieTrakerLastCheckedStore.set({ FoundNewEpisodes: false, LastChecked: encodeDate(new Date()) }); delete serieTrakerLastCheckedStore; var serieStore = Enbalaba.GetLocalStore("trackedSeriesInfo"), serieInfo = serieStore.get(); if (!serieInfo.Ids) serieStore.set({ Ids: [], CurrentId: 1 }); $("div.results").after("<div class='results' id='serieContainer'><dl></dl><div id='addSerieContainer' style='float:left;position:relative;'> <h2>Track a new Serie</h2>" + "<div class='row'><div class='col1'><label>Name</label></div><div class='col2'><input type='text' id='st_tbNameNew' class='bcTextbox'/></div> <div class='col3'><span id='st_lblSuggestion'></span></div></div>" + "<div class='row'><div class='col1'><label>Season</label></div><div class='col2'><select id='st_ddSeasonNew' class='bcSelect'><option></option></select></div></div>" + "<div class='row'><div class='col1'><label>Episode</label></div><div class='col2'><select id='st_ddEpisodeNew' class='bcSelect'><option></option></select></div></div>" + "<button type='button' id='btAddSerie' class='bcButton'>Add This Serie</button><span id='st_lblOutput' style='color:red'></span><br/>" + "<input type='checkbox' id='cbIsFinishedSeason'/><label for='cbIsFinishedSeason'>I know this season is finished and has </label><input type='input' id='tbSeasonNbEpisodes' style='width:20px' maxlength=2 value='20'/> episodes</div>" //+ "<div id='st_lblNotes' style='position:absolute;top:30px;left:30px' >Bobcat-Torrentz will check once a day for new episodes of tracked series<div/>" + "</div>" + "<div style='clear:both;cursor:pointer' id='st_btDeleteAll' >Delete All Tracked Series<div/>" + "<div style='width:500px;border-radius:6px; border-size:1px;margin-top:25px'>The Bobcat addon will check once a day your tracked series for new episodes.<br/><img src='http://i.imgur.com/n7tvk8I.png'/>: New episode(s)<br/><img src='http://i.imgur.com/tDWKswF.png'/>: No new episodes</div>"); //$("div.note").css("width", "400px").html("The Bobcat addon will check once a day your tracked series for new episodes.<br/><img src='http://i.imgur.com/n7tvk8I.png'/>:New episode(s)<br/><img src='http://i.imgur.com/tDWKswF.png'/>: No new episodes"); /*Populate dropdowns*/ var i, htmlddSeasons = "", htmlddEpisodes = ""; for (i = 1; i < 16; i++) htmlddSeasons += "<option value='" + i + "'>" + i + "</option>"; for (i = 1; i < 31; i++) htmlddEpisodes += "<option value='" + i + "'>" + i + "</option>"; $("#st_ddSeasonNew").html(htmlddSeasons); $("#st_ddEpisodeNew").html(htmlddEpisodes); htmlddSeasons = ""; //blank variable because of closures htmlddEpisodes = ""; /*Display Series*/ this.displayTrackedSeries(); /*Search for new*/ this.searchForNewEpisodes(this.episodeFoundCallback); /*Add Serie event*/ var that = this; $("#btAddSerie").click(function () { var name = $("#st_tbNameNew").val(); if ($.trim(name) == "") { $("#st_lblOutput").text("Enter a Name"); //$("#st_tbNameNew").css("border-color", "red"); } else { //---ADDITION var store = Enbalaba.GetLocalStore("trackedSeriesInfo"), serieInfo = store.get() , id = serieInfo.CurrentId; serieInfo.CurrentId = id + 1; serieInfo.Ids.push(id); store.set(serieInfo); var store = Enbalaba.GetLocalStore("ts_" + id) , isFinished = $("#cbIsFinishedSeason").is(":checked") , serie = { Name: name, Season: parseInt($("#st_ddSeasonNew").val(), 10), Current: { e: parseInt($("#st_ddEpisodeNew").val(), 10) }, History: [], id: id }; if (isFinished) { serie.isFinished = true; serie.NbTotEpisodes = parseInt($("#tbSeasonNbEpisodes").val(), 10); if (isNaN(serie.NbTotEpisodes)) { alert("Enter a valid number of episodes"); return; } } store.set(serie); that.displayTrackedSeries(); that.searchForNewEpisodes(that.episodeFoundCallback); //that.displayTrackedSeries(serieStore); $("#st_lblOutput").text(""); } }); $("#st_lblSuggestion").click(function () { $("#st_tbNameNew").val($(this).text()); }); $("#st_tbNameNew").keypress(function (e) { if (e.keyCode >= 20 && e.keyCode <= 40 && e.keyCode != 32) return true; //arrows, shift, and other keys that don't change the input. 32 is 'space' var txt = $(this).val(); if (txt.length >= 3) { var url = encodeURI("http://torrentz.eu/suggestions.php?q=" + $.trim(txt)/*.replace(' ', '+')*/); $("<span></span>").css("display", "none").load(url, function (data) { var res = $.parseJSON(data); if (res && res.length == 2 && res[1] != null && res[1].length > 0) { console.log(res[1][0]); $("#st_lblSuggestion").text(res[1][0]); } else $("#st_lblSuggestion").val("-"); }); } }); $("#st_btDeleteAll").click(function () { if (confirm("Do you want to delete all the currently tracked series ?")) { Enbalaba.GetLocalStore("trackedSeriesInfo").set({ Ids: [], CurrentId: 1 }); that.displayTrackedSeries(); } }); } this.SerieTrackerMode = true; } else { this.SerieTrackerMode = false; $("div.results h3,div.recent").nextAll().show(); $("#serieContainer").hide(); $("#btSerieTracker").text("Serie Tracker"); } } , displayTrackedSeries: function () { var serieIds = Enbalaba.GetLocalStore("trackedSeriesInfo").get().Ids; var dl = $("#serieContainer dl"); dl.empty(); for (var i = 0, serie, id; i < serieIds.length; i++) { this.displaySerie(serieIds[i]); } } , displaySerie: function (serieId) { var serie = Enbalaba.GetLocalStore("ts_" + serieId).get(), time , hasNew = false; if (!serie.History) serie.History = []; var html = "<div class='trackedSerieContainer' data-id='" + serie.id + "'>" + "<div class='trackedSerieHeader'>" + "<div class='st_name st-col1'>" + "<div class='deleteIcon fleft' data-id='" + serie.id + "' title='delete' style='margin-right:2px'></div>" + serie.Name + "</div>" + "<div class='st-col2'><b>Season " + serie.Season + "</b></div>" + "<div class='episode st-col3'><b>" + (serie.History.length > 0 ? "Episode " + serie.History[0].e : " - ") + "</b></div>" + "<div class='st-col4'>" + (serie.isFinished ? "" : "Tracking: On") + "</div>" + "</div>" + "<div class='trackerSerieBody' style='display:none'>"; //History if (serie.History.length == 0) { html += "<div style='margin-left:50px'>No results found</div>"; } else { for (var j = 0, h, d, l = serie.History.length; j < l; j++) { h = serie.History[j]; d = (h.d ? new Date(new Date() - getDateFromDateString(h.d)) : null); if (d) { if (d.getMonth() > 0) { dif = d.getMonth() + " month" + (d.getMonth() == 1 ? "" : "s") + " ago"; } else { time = d.getDate() - 1; if (time == 0) { time = "today"; hasNew = true; } else time += " days ago"; } } html += "<div class='st-row' data-serieData='" + (serie.id + "_" + h.e) + "'><div class='st-col1'> </div> <div class='st-col2'>Episode " + h.e + "</div><div class='st-col3'>" + (h.f ? "<span class='st-btShowLk hyperlink'>Show Links<span>" : "<span>Not found</span>") + "</div>" + "<div class='st-col4'>" + time + "</div>" + "</div> "; } } html += "</div></div>"; var el = $("#serieContainer .trackedSerieContainer").filter(function () { return $(this).data("id") == serieId; }), newEl = $(html); delete html; //for the closure if (el.length > 0) el.empty().replaceWith(newEl); else $("#serieContainer dl").append(newEl); var that = this; newEl.find("div.deleteIcon").click(function (e) { e.stopImmediatePropagation(); that.onclick_deleteTrackedSerie(this); }); newEl.find("span.st-btShowLk").click(function (e) { that.onclick_showLinks(this); }); newEl.find("div.trackedSerieHeader").addClass(hasNew ? "hasNew" : "").click(function (e) { that.onclick_serieHeader(this); }); } // Once a day, the serie tracker check if there are new episodes available. , checkForNewEpisodes: function () { var serieTrakerLastCheckedStore = Enbalaba.GetLocalStore("serieTrackerLastCheck"), serieTrakerLastChecked = serieTrakerLastCheckedStore.get(), today = encodeDate(new Date()); if (!serieTrakerLastChecked || serieTrakerLastChecked.LastChecked != today) { //Start daily search serieTrakerLastCheckedStore.set({ FoundNewEpisodes: false, LastChecked: today }); this.searchForNewEpisodes(this.episodeFoundCallback_2); } else if (serieTrakerLastChecked.FoundNewEpisodes) { //A search was previously done, but the user didn't go to the serie tracker. Add a specific icon to signal new episode available. $("#btSerieTracker").css("color", "Blue").removeClass("bobcatStamp").addClass("bobcatStamp2"); } } , searchForNewEpisodes: function (callback) { var serieInfo = Enbalaba.GetLocalStore("trackedSeriesInfo").get() , that = this , today = encodeDate(new Date()); for (var i = 0, store, serie, search, ids = serieInfo.Ids; i < ids.length; i++) { //serie = series[i]; store = Enbalaba.GetLocalStore("ts_" + ids[i]); serie = store.get(); if (!serie.isFinished || serie.History.length == 0) { this.lookForEpisode(serie, serie.Current.e, callback, store); } } } , lookForEpisode: function (serie, episode, callback, store) { var search = serie.Name + " S" + (serie.Season < 10 ? "0" : "") + serie.Season + "E" + (episode < 10 ? "0" : "") + episode , url = encodeURI("http://torrentz.eu/search?f=" + search) , that = this; //console.info(url); search = search.toLowerCase(); $("<span></span>").css("display", "none").load(url, function (data) { var rows = $(this).find("div.results dl"), results = []; //console.info(rows.length + " results"); for (var i = 0, $row, txt; i < rows.length; i++) { $row = $(rows[i]); txt = $row.find("dt").text().toLowerCase(); if (txt.indexOf(search) > -1) { //we need to be sure the results returned are related to the search results.push($row); } } if (callback) callback(serie, episode, results, store, that); $(this).empty(); //free memory of the temporary div }); } , episodeFoundCallback: function (s, e, results, store, context) { if (results.length < 1) { //NO EPISODE FOUND if (s.isFinished && e < s.NbTotEpisodes) { s.History.splice(0, 0, { e: e, f: false, d: encodeDate(new Date()) }); //insert new entry in history - at the begining s.Current.e = parseInt(s.Current.e, 10) + 1; store.set(s); context.displaySerie(s.id); //redisplay the result for the serie context.lookForEpisode(s, e + 1, context.episodeFoundCallback, store); //rec } } else { //EPISODE FOUND //console.info("New episode Found for " + s.Name); //New episode found s.History.splice(0, 0, { e: e, f: true, d: encodeDate(new Date()) }); //insert new entry in history - at the begining s.Current.e = parseInt(s.Current.e, 10) + 1; store.set(s); context.displaySerie(s.id); //redisplay the result for the serie var el = $("#serieContainer .trackedSerieContainer").filter(function () { return $(this).data("id") == s.id; }); el.find(".trackedSerieHeader").css("color", "Blue"); context.lookForEpisode(s, s.Current.e, context.episodeFoundCallback, store); //rec } } /*Function called the first time the user visit torrentz in the day, even if he hasn't entered the Section Tracker section*/ , episodeFoundCallback_2: function (s, e, results) { if (results.length < 1) return; $("#btSerieTracker").css("color", "Blue"); //.text("Serie Tracker ( New Episodes! )"); var serieTrakerLastCheckedStore = Enbalaba.GetLocalStore("serieTrackerLastCheck") , serieTrakerLastChecked = serieTrakerLastCheckedStore.get(); serieTrakerLastCheckedStore.set({ FoundNewEpisodes: true, LastChecked: encodeDate(new Date()) }); } , onclick_serieHeader: function (headerEl) { headerEl = $(headerEl); var body = headerEl.parent().children(".trackerSerieBody"); if (body.is(":visible")) { //console.info("up"); body.slideUp(200, function () { }); } else body.slideDown(200, function () { }); //$(this).parent().data("id")); } , onclick_showLinks: function (lk) { lk = $(lk); var row = lk.parent().parent() , that = this , data = row.data("seriedata"), dataParts; //row store some data : serieId_episodeNumber var existingBox = row.parent().children(".st-link-container").filter(function () { return $(this).data("seriedata") == data; }); if (existingBox.length != 0) { existingBox.remove(); //row.parent().remove(existingBox); } else { if (data) { dataParts = data.split('_'); //"serieId _episodeNumber" var serie = this.getSerieFromStore(dataParts[0]); this.lookForEpisode(serie, dataParts[1], function (s, e, results) { var html = "<div class='st-link-container' data-seriedata='" + data + "'>" , max = (results.length < 3 ? results.length : 3); for (var i = 0; i < max; i++) { //show only 3 first r = results[i]; that.processRow(r, null, true); html += "<div class='st-row'><div class='st-link-col1'>" + r.find("dt").html() + "</div>"; html += "<div class='st-link-col2'>" + r.find("dd").html() + "</div> "; html += "</div>"; } var linkContainer = $(html); linkContainer.find("span.downloadLink").click(function () { downloadTorrent($(this).attr("data-torrentid")); }); row.after(linkContainer); }); } } } , onclick_deleteTrackedSerie: function (element) { //serie deletion var name = $(element).parent().text(), id = $(element).data('id'); if (confirm("Are you sure you want to delete the entry for '" + name + "'")) { var store = Enbalaba.GetLocalStore("trackedSeriesInfo"), serieInfo = store.get(); serieInfo.Ids = $.grep(serieInfo.Ids, function (value) { return value != id; }); store.set(serieInfo); store = Enbalaba.GetLocalStore("ts_" + id); //.get(); store.set({}); //TODO : real deletion this.displayTrackedSeries(); //console.info("deleted"); } //else console.info("Not deleted"); } , getSerieFromStore: function (id) { var serieStore = Enbalaba.GetLocalStore("ts_" + id), serie = serieStore.get(); return serie; } } //Basic Class to deal with the localstorage Enbalaba = {}; //Add CSS function initCss() { var css = [ " .rateBox{ margin-left:10px;position:relative;bottom:3px; cursor: pointer; padding:1px; background-color:#EEE; border:#AAA solid 1px; border-radius:4px}" , ".bobcatLogo{background:transparent url(http://i.imgur.com/MlVVyzX.png) no-repeat scroll 0 0}" , "#bobcatLogoContainer a{color:White}" , "#bobcatLogoContainer a:hover{color:White}" , ".bobcatStamp{background:transparent url(http://i.imgur.com/tDWKswF.png) no-repeat scroll 0 0}" , ".bobcatStamp2{background:transparent url(http://i.imgur.com/n7tvk8I.png) no-repeat scroll 0 0}" , "#bobcatLogoContainer{color:White;height:30px;width:150px;float:left;padding-left:50px;padding-top:5px; margin-top:10px}" , ".downloadLink{;margin-right:20px}" , ".moreLk{padding-left:30px;cursor:pointer}" , ".movieDesc{width:530px;margin:10px 0px 40px 0px;color:Black;white-space:normal}" , ".fleft{ float:left}" , "dt:hover{ background-color:#EEE}" , ".qualityComments{float:clear}" , ".spinner{ background:url(http://www.andrewdavidson.com/articles/spinning-wait-icons/wait16trans.gif) no-repeat left center;width: 16px;height: 16px}" , ".actorsInfo,.qualityComments,.divQuality,.plot{ margin-top:11px;margin-bottom:5px; font-size:12px;font-family:Verdana,Tahoma,sans-serif}" , "#pluginZoneContainer{ position:absolute; left: 210px; top:10px; width: 200px; height: 200px;background-color:Gray}" , ".expand{ background:transparent url(http://i.imgur.com/mIIop2R.png) no-repeat scroll 0 0; width:15px; height: 9px; position: relative; top:3px}" //arrow1.png , ".deleteIcon{ background:transparent url(http://i.imgur.com/4RjuUFU.png) no-repeat scroll 0 0; width:15px; height: 13px; position: relative; top:3px}" , ".downloadIcon{ background:transparent url(http://i.imgur.com/7Jkx1N9.png) no-repeat scroll 0 0; width:17px; height: 18px; position: relative; top:3px}" , ".deleteIcon:hover{ background-color:#CCC}" , ".collapse{ background-image:url(http://i.imgur.com/apcKFJ5.png)}"//arrow2.png , ".btSerieTrackerHighlight{color:Yellow !important}" , "#btSerieTracker{ padding-left:40px;margin-left:20px; background-color:White;background-position:3px 3px}" , "#addSerieContainer{ width:50%; border: 1px solid #B5B8C8; margin: 30px 0px; padding:20px; border-radius: 15px}" , "#st_tbNameNew{ width : 150px}" , "#btAddSerie{ margin: 10px 0px}" , "#cbIsFinishedSeason{margin-right:7px}" , "#st_lblSuggestion{ color:Grey; font-size:11px;cursor:pointer}" , ".trackedSerieHeader{ margin: 15px 0px}" , ".trackedSerieHeader,.st-row{clear:both;width:100%;font-size:12px;height:15px}" , ".trackedSerieHeader>div,.st-row>div{ margin-right:30px;float:left}" , ".st-col1{ width:200px}" , ".st-col2,.st-col3{ width:100px}" , ".st-link-col1{width:500px}" , ".st_name{font-weight:bold}" , " .st-link-container{margin:10px; border:1px solid #AAA;padding:20px}" , ".st-link-col2 span{ margin-right:10px}" , ".st-link-col2 .u{ font-weight:bold}" , "div.trackedSerieHeader{cursor:pointer}" , "div.trackedSerieHeader:hover{ background-color:#EEE}" , ".hasNew{color:Blue}" //Generic , ".hyperlink{color:#0066EE;text-decoration:none;cursor:pointer;text-decoration:underline}" , ".bcButton{color:#6B3F2E; border-radius: 6px; border: 1px solid #6B3F2E; height:25px; padding-bottom:1px; min-width:80px; font-weight:bold;cursor:pointer}" , ".bcButton:hover{color:#AA3F2E; }" , ".bcTextbox{background-color:#FFF;border: 1px solid #B5B8C8; font-size: 14px; height: 16px; line-height: 14px; padding: 2px; vertical-align: middle;border-radius: 5px; color:color:#6B3F2E}" , ".bcSelect{ background-color:#FFFFFF;height:26px;line-height:26px;border:1px solid #CCCCCC;color:Black;font-size:16px; padding:4px;border-radius:5px}" , " .col1{ float:left; width:100px; }" , ".col2{ float:left; width:200px}" , ".col3{ float:left; width:200px}" , ".row{ clear:both; width : 500px; margin:10px 0px; padding-bottom:20px}" ]; css = css.join("\n"); if (typeof GM_addStyle != "undefined") GM_addStyle(css); else if (typeof PRO_addStyle != "undefined") PRO_addStyle(css); else if (typeof addStyle != "undefined") addStyle(css); else { var heads = document.getElementsByTagName("head"); if (heads.length > 0) { var node = document.createElement("style"); node.type = "text/css"; node.appendChild(document.createTextNode(css)); heads[0].appendChild(node); } } } /*Parse a string with a basic format (yyyyMMdd HHmmss) to a date object */ function getDateFromDateString(dateString, isUTCDate) { try { //This is for Javascript to understand format 'yymmdd hhmmmss' var year = dateString.substring(0, 4), month = dateString.substring(4, 6), day = dateString.substring(6, 8), hours = dateString.substring(9, 11), minutes = dateString.substring(11, 13), seconds = dateString.substring(13, 15); var date = new Date(year, month - 1, day, hours, minutes, seconds, "00"); // months are 0-based if (isUTCDate == true) { //Must convert the date from UTC/GMT to local time var n = date.getTimezoneOffset(); date.setMinutes(date.getMinutes() - n); } return date; } catch (err) { return new Date(dateString); } } /** Encode a date : "yyyyMMdd" */ function encodeDate(d) { //debugger; var twoDigit = function (val) { if (val < 10) return "0" + val; else return val; }; if (d && d.getMonth) return d.getFullYear().toString() + twoDigit((d.getMonth() + 1)) + twoDigit(d.getDate()); // + " " + twoDigit(d.getHours()) + twoDigit(d.getMinutes()) + twoDigit(d.getSeconds()); else return null; } function downloadTorrent(id){ if (!id) return; var hiddenIFrameID = 'hiddenDownloader', //url = "http://torcache.net/?download=" + id; url = "http://torrage.com/torrent/" + id; iframe = document.getElementById(hiddenIFrameID); if (iframe===null) { iframe = document.createElement('iframe'); iframe.id = hiddenIFrameID; iframe.style.display = 'none'; document.body.appendChild(iframe); console.log("SRC : "+url); } iframe.src = url; } //--Application specific. Ensure Singleton, single location to set up the specific configs. Better to use that than using new Enbalaba.LocalStore() Enbalaba.GetLocalStore = (function () { var _stores = []; //*Private* return function (name) { if (!_stores[name]) { var config = {}; switch (name) { case "moviesInfo": config = { MaxProperties: 100 }; break; case "trackedSeries": config = { IsArray: true }; break; } _stores[name] = new Enbalaba.LocalStore(name, config); } return _stores[name]; } })(); //-------------- Enbalaba.LocalStore = function (name, config) { this.Name = name; var defaultConfig = { EmptyValue: {}, MaxTotalSize: 250000 }; //Notes : 1 char = 2octets (Strings in JavaScript are UTF-16, so each character requires two bytes of memory) if (!config) config = {}; else { if (config.IsArray == true) defaultConfig = { EmptyValue: [], MaxItems: 100, MaxTotalSize: 250000 }; //MaxTotalSize for arrays (usually used for MRU)== 500Ko } this.Config = $.extend(defaultConfig, config); }; Enbalaba.LocalStore.prototype = { _isSupported: !(typeof localStorage == 'undefined' || typeof JSON == 'undefined'), set: function (val) { if (this._isSupported) { if ($.isArray(val) && val.length > this.Config.MaxItems) { for (var i = 0, dif = val.length - this.Config.MaxItems; i < dif; i++) val.shift(); //remove X first elements } var s = JSON.stringify(val); if (s.length > this.Config.MaxTotalSize) return false; //todo: something more significant localStorage.setItem(this.Name, s); return true; } } /*Get the value associated with the store are. Can return null, except if Config.EmptyValue has been defined */ , get: function () { if (this._isSupported) { var s = localStorage.getItem(this.Name); if (s != null && s != "") { return JSON.parse(s); } else if (this.Config.EmptyValue) return this.Config.EmptyValue; } if (this.Config.EmptyValue) return this.Config.EmptyValue; return null; } }; Torrentz.GM.BobCatTorrentz.start();