javascript: /*
MyAnimeList-Tools
A CSS Generator and Tag updater
- Original code 2018/Aug/10 by BurntJello http://burntjello.webs.com
- Extra features 2019 by Cateinya
- Fixes 2020/Oct by Cry5talz
- Further changes 2021+ by Valerio Lyndon
*/
ver = '6.0';
verMod = '2022/May/08';
defaultSettings = {
"css_template": "/* [TITLE] *[DEL]/ .data.image a[href^=\"/[TYPE]/[ID]/\"]::before { background-image: url([IMGURL]); }",
"delay": "3000",
"match_template": "/[TYPE]/[ID]/",
"update_tags": false,
"checked_tags": {
"english_title": false,
"french_title": false,
"spanish_title": false,
"german_title": false,
"native_title": false,
"season": false,
"year": false,
"genres": false,
"themes": false,
"demographic": false,
"authors": false,
"score": false,
"rank": false,
"studio": false,
"producers": false,
"licensors": false,
"serialization": false,
"aired": false,
"published": false,
"rating": false,
"duration": false,
"totalduration": false
},
"clear_tags": false,
"check_existing": false
};
if(localStorage.getItem('burnt_settings') !== null)
{
try
{
settings = JSON.parse(localStorage.getItem('burnt_settings'));
/* Check for missing settings and fill them in. This prevents errors while maintaining user settings, especially in the case of a user updating from an older version. */
for(key in defaultSettings)
{
if (!(key in settings))
{
settings[key] = defaultSettings[key];
}
}
for(key in defaultSettings['checked_tags'])
{
if (!(key in settings['checked_tags']))
{
settings['checked_tags'][key] = defaultSettings['checked_tags'][key];
}
}
}
catch(e)
{
alert("Encountered an error while parsing your previous settings. Your settings have been reverted to defaults. To quickly recover your template settings, try selecting \"Last Run\" and then \"Autofill\". Other settings will need to be manually set. \n\nIf you've never run this tool before, you should never see this.");
settings = defaultSettings;
}
}
else
{
settings = defaultSettings;
}
/* TOOL CODE */
modernStyle = (document.getElementById("list_surround")) ? false : true;
animeManga = window.location.href.replace("https://myanimelist.net/", "").split("/")[0].replace("list", "");
/* Create GUI */
css(`
#burnt-bg, #burnt-gui {
position: fixed;
z-index: 99999;
}
#burnt-bg {
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.5);
}
#burnt-gui {
left: 50px;
top: 50px;
bottom: 50px;
right: 50px;
display: flex;
flex-flow: row nowrap;
background-color: #fff;
border-style: solid;
box-sizing: border-box;
color: #000;
font: 12px/1.5 sans-serif;
text-align: left;
}
.burnt-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9999;
background: rgba(0,0,0,0.5);
}
.burnt-popup {
position: fixed;
left: 50%;
top: 50%;
z-index: 9999;
min-width: 300px;
max-width: calc(100% - 100px);
min-height: 100px;
max-height: calc(100% - 100px);
padding: 10px;
background: #fff;
overflow: auto;
transform: translate(-50%,-50%);
}
.burnt-popup input:not([type="button"]),
.burnt-popup textarea {
display: block;
width: 100%;
max-width: 600px;
margin-bottom: 6px;
}
#burnt-status {
background: #e6e6e6;
padding: 2px 6px;
margin: 5px 0 10px;
--percent: 0%;
--colour: #4277f2;
background-image: linear-gradient(
to right,
var(--colour) var(--percent),
transparent var(--percent)
);
}
#burnt-time {
float: right;
}
#burnt-gui * {
box-sizing: inherit;
color: #000;
font: inherit;
}
#burnt-gui hr {
height: 4px;
background: #e6e6e6;
border: 0;
margin: 10px 0 15px;
}
#burnt-gui *:disabled {
opacity: 0.7;
}
.burnt-btn + .burnt-btn {
margin-left: 3px;
}
.burnt-chk {
display: block;
}
.burnt-tag {
margin-left: 10px;
}
.burnt-tag-disabled {
opacity: 0.5;
pointer-events: none;
}
.burnt-textarea {
width: 50%;
}
.burnt-textarea b {
display: inline-block;
height: 24px;
}
.burnt-textarea-btn {
height: 20px;
padding: 0 2px;
margin-left: 3px;
float: right;
}
#burnt-gui textarea {
display: block;
width: 100%;
height: calc(100% - 24px);
margin: 0;
resize: none;
font-family: monospace;
word-break: break-all;
}
`);
gui = document.createElement("div");
gui.id = "burnt-gui";
bg = $('
');
overlay = $('');
$('body').append(bg);
$('body').append(gui);
guiL = document.createElement('div');
gui.appendChild(guiL);
guiL.style.cssText = `
width: 250px;
padding: 10px 0 10px 10px;
overflow-x: hidden;
overflow-y: auto;
flex: 0 0 auto;
`;
guiR = document.createElement('div');
gui.appendChild(guiR);
guiR.style.cssText = `
display: flex;
width: 90%;
padding: 10px;
flex: 1 1 auto;
flex-flow: row nowrap;
`;
thumbBtn = document.createElement("input");
guiL.appendChild(thumbBtn);
thumbBtn.classList.add('burnt-btn');
thumbBtn.type = "button";
thumbBtn.value = "Loading...";
thumbBtn.disabled = 'disabled';
thumbBtn.onclick = function() { Process(); };
exitBtn = document.createElement("input");
guiL.appendChild(exitBtn);
exitBtn.classList.add('burnt-btn');
exitBtn.type = "button";
exitBtn.value = "Exit";
function Exit()
{
$('#burnt-bg').remove();
$('#burnt-gui').remove();
$('.burnt-css').remove();
}
exitBtn.onclick = Exit;
statusBar = document.createElement("div");
statusBar.id = "burnt-status";
guiL.appendChild(statusBar);
statusText = document.createElement('span');
statusText.textContent = 'Setting up...';
statusBar.style.cssText = '--percent: 20%; --colour: #60ce81;';
statusBar.appendChild(statusText);
timeText = document.createElement('span');
timeText.id = 'burnt-time';
statusBar.appendChild(timeText);
function field(value, title, desc) {
lbl = document.createElement('label');
lbl.textContent = title;
lbl.style.display = 'inline-block';
lbl.style.marginRight = '10px';
lbl.style.marginBottom = '5px';
lbl.style.fontWeight = '700';
lbl.style.textAlign = 'left';
$(lbl).append($(' '));
input = document.createElement('input');
input.type = 'text';
input.style.width = '100%';
input.value = value;
input.title = desc;
input.style.fontWeight = '400';
input.spellcheck = false;
lbl.appendChild(input);
guiL.appendChild(lbl);
return input;
}
function chk(checked, title, className = false, desc = false) {
var lbl = document.createElement('label');
lbl.textContent = title;
if(desc) {
lbl.title = desc;
}
if(className) {
lbl.className = className;
}
var chk = document.createElement("input");
chk.type = "checkbox";
chk.checked = checked;
lbl.prepend(chk);
guiL.appendChild(lbl);
return chk;
}
/* Options section */
delay = field(settings['delay'], "Delay", "Delay (ms) between requests to avoid spamming the server.");
delay.style.width = "50px";
matchTemplate = field(settings['match_template'], "Match Template", "Line matching template for reading previously generated code. Should match the ID format of your template. Only matching on [ID] is not enough, include previous/next characters to ensure the match is unique.");
template = field(settings['css_template'], "Template", "CSS template. Replacements are:\n[TYPE], [ID], [IMGURL], [IMGURLT], [IMGURLV], [IMGURLL], [TITLE], [TITLEEN], [TITLEFR], [TITLEES], [TITLEDE], [TITLERAW], [GENRES], [THEMES], [DEMOGRAPHIC], [RANK], [SCORE], [SEASON], [YEAR], [STARTDATE], [ENDDATE], and [DESC].\n\nAnime only:\n[STUDIOS], [PRODUCERS], [LICENSORS], [RATING], [DURATIONEP], [DURATIONTOTAL]\n\nManga only:\n[AUTHORS], [SERIALIZATION]");
template.parentNode.style.width = "100%";
$(guiL).append($(' '));
chkTags = chk(settings['update_tags'], "Update Tags:", 'burnt-chk burnt-tagtoggle');
chkTags.parentNode.addEventListener('click', toggleTags);
function toggleTags() {
bool = chkTags.checked;
if(bool) {
$('.burnt-tag').removeClass('burnt-tag-disabled');
} else {
$('.burnt-tag').addClass('burnt-tag-disabled');
}
}
chkEnglish = chk(settings['checked_tags']['english_title'], "English title", 'burnt-chk burnt-tag');
chkFrench = chk(settings['checked_tags']['french_title'], "French title", 'burnt-chk burnt-tag');
chkSpanish = chk(settings['checked_tags']['spanish_title'], "Spanish title", 'burnt-chk burnt-tag');
chkGerman = chk(settings['checked_tags']['german_title'], "German title", 'burnt-chk burnt-tag');
chkNative = chk(settings['checked_tags']['native_title'], "Native title", 'burnt-chk burnt-tag');
chkSeason = chk(settings['checked_tags']['season'], "Season", 'burnt-chk burnt-tag');
chkYear = chk(settings['checked_tags']['year'], "Year", 'burnt-chk burnt-tag');
chkGenres = chk(settings['checked_tags']['genres'], "Genres", 'burnt-chk burnt-tag');
chkThemes = chk(settings['checked_tags']['themes'], "Themes", 'burnt-chk burnt-tag');
chkDemographic = chk(settings['checked_tags']['demographic'], "Demographic", 'burnt-chk burnt-tag');
chkScore = chk(settings['checked_tags']['score'], "Score", 'burnt-chk burnt-tag');
chkRank = chk(settings['checked_tags']['rank'], "Rank", 'burnt-chk burnt-tag');
/*Anime Only */
chkStudio = chk(settings['checked_tags']['studio'], "Studio", 'burnt-chk burnt-tag');
chkProducers = chk(settings['checked_tags']['producers'], "Producers", 'burnt-chk burnt-tag');
chkLicensors = chk(settings['checked_tags']['licensors'], "Licensors", 'burnt-chk burnt-tag');
chkAired = chk(settings['checked_tags']['aired'], "Aired", 'burnt-chk burnt-tag');
chkRating = chk(settings['checked_tags']['rating'], "Rating", 'burnt-chk burnt-tag');
chkDuration = chk(settings['checked_tags']['duration'], "Duration (Episode)", 'burnt-chk burnt-tag');
chkTotalDuration = chk(settings['checked_tags']['total_duration'], "Duration (Total)", 'burnt-chk burnt-tag');
/*Manga only*/
chkPublished = chk(settings['checked_tags']['published'], "Published", 'burnt-chk burnt-tag');
chkAuthors = chk(settings['checked_tags']['authors'], "Authors", 'burnt-chk burnt-tag');
chkSerialization = chk(settings['checked_tags']['serialization'], "Serialization", 'burnt-chk burnt-tag');
if(animeManga === 'anime') {
chkPublished.parentNode.style.display = 'none';
chkAuthors.parentNode.style.display = 'none';
chkSerialization.parentNode.style.display = 'none';
} else {
chkStudio.parentNode.style.display = 'none';
chkProducers.parentNode.style.display = 'none';
chkLicensors.parentNode.style.display = 'none';
chkAired.parentNode.style.display = 'none';
chkRating.parentNode.style.display = 'none';
chkDuration.parentNode.style.display = 'none';
chkTotalDuration.parentNode.style.display = 'none';
}
$(guiL).append($(' '));
chkClearTags = chk(settings['clear_tags'], "Overwrite current tags", 'burnt-chk burnt-tag', "Overwrite all of your current tags with the new ones. If all other tag options are unchecked, this will completely remove all tags.\n\nDO NOT use this if you have any tags you want to keep.");
$(guiL).append($(' '));
chkExisting = chk(settings['check_existing'], "Validate existing images", 'burnt-chk', "Attempt to load all images, updating the url if it fails. There is a 5 second delay to allow images to load. Not recommended while adding new anime or updating tags!");
$(guiL).append($(''));
/* Import/Export section */
importBtn = $('');
importBtn.click(function() {
$(gui).append(overlay);
importOverlay = $(`
Input a template here. This will update the tool settings and may add some additional code to your MAL Custom CSS. You may wish to backup your Custom CSS before doing this.
`);
$(gui).append(importOverlay);
$('#burnt-import-btn').click(function() {
value = $('#burnt-import-field').val();
if(value.length < 1)
{
alert('Nothing detected in import field.');
}
else
{
try
{
importedTemplate = JSON.parse(value);
if(!("template" in importedTemplate) || !("matchtemplate" in importedTemplate))
{
alert(`Import failed due to incorrect syntax or missing information.`);
}
else
{
if(!("css" in importedTemplate))
{
importedTemplate['css'] = '';
}
t = setTemplate(importedTemplate['template'], importedTemplate['matchtemplate'], importedTemplate['css']);
if(!t)
{
alert('Import failed to update MAL Custom CSS. This is likely due to a code error and should be reported to the developer.');
}
else
{
alert('Import succeeded.');
}
importOverlay.remove();
overlay.remove();
}
}
catch(e)
{
alert(`Import failed. If you are using an official template, report this problem to the developer with the following information.\n\nError message for reference:\n${e}\n\nValue for reference:\n${value}`);
}
}
});
$('#burnt-close').click(function() {
importOverlay.remove();
overlay.remove();
});
});
$(guiL).append(importBtn);
exportBtn = $('');
exportBtn.click(function() {
$(gui).append(overlay);
exportOverlay = $(`
Use this to create a template. The template and match template are required, but you may leave the CSS Styling field blank if desired.