| @@ -138,6 +138,54 @@ function remove_score(anime_id) { | |||||
| }); | }); | ||||
| } | } | ||||
| function export_scores() { | |||||
| chrome.storage.sync.get(null, function(dat) { | |||||
| var blob = new Blob([JSON.stringify(dat)], {type: "application/json"}); | |||||
| $($("<a>") | |||||
| .attr("href", window.URL.createObjectURL(blob)) | |||||
| .attr("download", "animelist_decimal_scores.json") | |||||
| .hide() | |||||
| .appendTo($("body"))[0].click()).remove(); | |||||
| }); | |||||
| } | |||||
| function validate_score_data(data) { | |||||
| if (!$.isPlainObject(data)) | |||||
| throw "invalid data type: " + data; | |||||
| if (JSON.stringify(data).length > chrome.storage.sync.QUOTA_BYTES) | |||||
| throw "file too large"; | |||||
| for (var bucket_id in data) { | |||||
| if (data.hasOwnProperty(bucket_id)) { | |||||
| if (isNaN(parseInt(bucket_id) || bucket_id >= MAX_BUCKETS)) | |||||
| throw "invalid bucket ID: " + bucket_id; | |||||
| var bucket = data[bucket_id]; | |||||
| if (!$.isPlainObject(bucket)) | |||||
| throw "invalid bucket type: " + bucket; | |||||
| for (var anime_id in bucket) { | |||||
| if (data.hasOwnProperty(anime_id)) { | |||||
| if (isNaN(parseInt(anime_id))) | |||||
| throw "invalid anime ID: " + anime_id; | |||||
| if (parseInt(anime_id) % MAX_BUCKETS != bucket_id) | |||||
| throw "anime is in the wrong bucket: " + anime_id; | |||||
| var score = parseFloat(bucket[anime_id]); | |||||
| if (isNaN(score)) | |||||
| throw "score is not a number: " + score; | |||||
| if ((score < 1 || score > 10) && score != 0) | |||||
| throw "score out of range: " + score; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| function import_scores(data, callback) { | |||||
| validate_score_data(data); | |||||
| chrome.storage.sync.clear(function() { | |||||
| chrome.storage.sync.set(data, callback); | |||||
| }); | |||||
| } | |||||
| /* ----------------------- Event patches/injections ------------------------ */ | /* ----------------------- Event patches/injections ------------------------ */ | ||||
| function update_list_score(anime_id) { | function update_list_score(anime_id) { | ||||
| @@ -307,15 +355,13 @@ function hook_list() { | |||||
| $("span[id^='scoreval']").each(function(i, elem) { | $("span[id^='scoreval']").each(function(i, elem) { | ||||
| var anime_id = elem.id.split("scoreval")[1]; | var anime_id = elem.id.split("scoreval")[1]; | ||||
| $(elem).after($("<span>") | |||||
| .css("display", "none").text($(elem).text())); | |||||
| $(elem).after($("<span>").hide().text($(elem).text())); | |||||
| load_score_into_element(data, anime_id, $(elem)); | load_score_into_element(data, anime_id, $(elem)); | ||||
| $("#scorediv" + anime_id) | $("#scorediv" + anime_id) | ||||
| .after($("<div>") | .after($("<div>") | ||||
| .attr("id", "scorediv" + anime_id) | .attr("id", "scorediv" + anime_id) | ||||
| .css("display", "none") | |||||
| .hide() | |||||
| .append($('<input>') | .append($('<input>') | ||||
| .attr("type", "text") | .attr("type", "text") | ||||
| .attr("id", "scoretext" + anime_id) | .attr("id", "scoretext" + anime_id) | ||||
| @@ -504,6 +550,80 @@ function hook_addtolist() { | |||||
| "page, and update the score.</p>").insertAfter($("#stype").parent()); | "page, and update the score.</p>").insertAfter($("#stype").parent()); | ||||
| } | } | ||||
| function hook_export() { | |||||
| chrome.storage.sync.getBytesInUse(null, function(usage) { | |||||
| usage = Math.round(usage / 1024 * 10) / 10; | |||||
| usage += " kB / " + chrome.storage.sync.QUOTA_BYTES / 1024 + " kB"; | |||||
| $("#dialog td") | |||||
| .append($("<hr>") | |||||
| .css("border", "none") | |||||
| .css("background-color", "#AAA") | |||||
| .css("height", "1px")) | |||||
| .append($("<p>") | |||||
| .html("The regular list export above will only include " + | |||||
| "rounded scores. You can export your decimal scores " + | |||||
| "separately and " + | |||||
| '<a href="http://myanimelist.net/import.php">import ' + | |||||
| "them</a> later.")) | |||||
| .append($("<div>") | |||||
| .attr("class", "spaceit") | |||||
| .html("Chrome Sync usage: " + usage)) | |||||
| .append($("<input>") | |||||
| .attr("type", "submit") | |||||
| .attr("value", "Export Decimal Scores") | |||||
| .attr("class", "inputButton") | |||||
| .click(export_scores)); | |||||
| }); | |||||
| } | |||||
| function hook_import() { | |||||
| $("#content").append($("<hr>") | |||||
| .css("border", "none") | |||||
| .css("background-color", "#AAA") | |||||
| .css("height", "1px")) | |||||
| .append($("<p>") | |||||
| .html("You can also import decimal scores here. Doing so will " + | |||||
| "erase any existing decimal scores.")) | |||||
| .append($("<div>") | |||||
| .attr("class", "spaceit") | |||||
| .append($("<input>") | |||||
| .attr("id", "decimal-file") | |||||
| .attr("size", "60") | |||||
| .attr("type", "file") | |||||
| .attr("class", "inputtext"))) | |||||
| .append($("<input>") | |||||
| .attr("id", "decimal-submit") | |||||
| .attr("type", "submit") | |||||
| .attr("value", "Import Decimal Scores") | |||||
| .attr("class", "inputButton") | |||||
| .click(function() { | |||||
| var filelist = $("#decimal-file")[0].files, file, reader; | |||||
| if (filelist.length != 1) | |||||
| return; | |||||
| file = filelist[0]; | |||||
| if (file.type != "application/json") { | |||||
| alert("Invalid file type: must be .json."); | |||||
| return; | |||||
| } | |||||
| reader = new FileReader(); | |||||
| reader.onload = function() { | |||||
| try { | |||||
| import_scores(JSON.parse(reader.result), function() { | |||||
| $("#decimal-file").after("<p>Success!</p>") | |||||
| .remove(); | |||||
| $("#decimal-submit").remove(); | |||||
| }); | |||||
| } catch (exc) { | |||||
| if (typeof exc === "object") | |||||
| alert("The file could not be parsed as JSON."); | |||||
| else | |||||
| alert("Error validating data: " + exc); | |||||
| } | |||||
| }; | |||||
| reader.readAsText(file); | |||||
| })); | |||||
| } | |||||
| /* ------------------------------- Main hook ------------------------------- */ | /* ------------------------------- Main hook ------------------------------- */ | ||||
| $(document).ready(function() { | $(document).ready(function() { | ||||
| @@ -524,5 +644,9 @@ $(document).ready(function() { | |||||
| hook_shared(); | hook_shared(); | ||||
| else if (href.contains("/addtolist.php")) | else if (href.contains("/addtolist.php")) | ||||
| hook_addtolist(); | hook_addtolist(); | ||||
| else if (href.contains("/panel.php") && href.contains("go=export")) | |||||
| hook_export(); | |||||
| else if (href.contains("/import.php")) | |||||
| hook_import(); | |||||
| } | } | ||||
| }); | }); | ||||