🏠 Home 

MyAnimeList(MAL) - Extra

Show anime/manga info inside your animelist/mangalist


Installer dette script?
// ==UserScript==
// @name         MyAnimeList(MAL) - Extra
// @version      5.2.0
// @description  Show anime/manga info inside your animelist/mangalist
// @author       Cpt_mathix
// @match        *://myanimelist.net/animelist/*
// @match        *://myanimelist.net/mangalist/*
// @license      GPL-2.0-or-later
// @namespace    https://greasyfork.org/users/16080
// ==/UserScript==
(function ($) {
var store = (function () {
var map = {};
return {
set: function (key, value) {
map[key] = value;
},
get: function (key) {
return map[key];
}
};
})();
var mal = {
href: document.location.href,
modern: false,
user: '',
type: []
};
init();
function init() {
mal.user = mal.href.match(/[^/]*?(?=\?|$)/)[0];
if (mal.href.indexOf("mangalist") > -1) {
mal.type = ["manga", 65];
} else {
mal.type = ["anime", 64];
}
mal.modern = $('.header .header-menu .btn-menu > .username').length > 0;
if (mal.modern) {
initGlobalScrollListener();
try {
setTimeout(initModernList, 1000);
} catch (ex) {
console.log(ex);
}
} else {
initOldList();
}
}
function initOldList() {
$('#list_surround > table > tbody > tr > td[class*=td]:nth-child(2)').each(function () {
var id = $(this).find('> a').attr('href').match(/\/(\d+)\//)[1];
var tdtype = $(this).attr('class').match(/\d/)[0];
var moreEl = $(this).find('> div > small > a:nth-child(2)');
var memberId = $('#listUserId').val();
var moreObject = $("#more" + id);
$(moreEl).removeAttr('onclick');
$(moreEl).attr("href", "javascript:;");
$(moreEl).on('click', displayTable(id, tdtype, moreObject, memberId));
});
}
function initModernList() {
$('#list-container > div.list-block > div > table > tbody[class=list-item] > tr.list-table-data > td.data.title').each(function () {
if ($(this).attr('id') === 'list-extra') {
return true;
} else {
$(this).attr('id', 'list-extra');
}
var id = $(this).find('> a').attr('href').match(/\/(\d+)\//)[1];
var moreEl = $(this).find('> div > span.more > a');
var memberId = $('body')[0].dataset.ownerId;
var moreObject = $("#more-" + id);
var el = $(moreEl)[0],
elClone = el.cloneNode(true);
el.parentNode.replaceChild(elClone, el);
$(elClone).attr("href", "javascript:;");
$(elClone).on('click', displayTable(id, 1, moreObject, memberId));
});
}
function initGlobalScrollListener() {
document.addEventListener("scroll", function scroll(event) {
// temporarily remove scroll listener to prevent multiple events
event.currentTarget.removeEventListener(event.type, scroll);
initModernList();
setTimeout(function () {
initGlobalScrollListener();
}, 1000);
});
}
//--------------------------------//
//       Get Data Functions       //
//--------------------------------//
function getAnimeInfo(animeid, table) {
var dataMap = store.get(animeid + 'MAP');
$.get('/' + mal.type[0] + '/' + animeid, function (data) {
$(data).find('#content .leftside > div.spaceit_pad:nth-child(n) > span:first-child').each(function () {
var item = this.textContent.replace(/:/g, "");
if (isNaN(item) && this.nextSibling) {
if (item == "Score") {
dataMap[item] = this.parentNode.querySelector('.score-label').textContent;
} else {
var props = this.parentNode.querySelectorAll('[itemprop]');
if (props.length > 0) {
dataMap[item] = [...props].map(prop => prop.nextElementSibling.outerHTML).join(", ");
} else if (this.nextSibling.textContent.trim() === "") {
dataMap[item] = this.nextElementSibling.outerHTML;
} else {
dataMap[item] = this.nextSibling.textContent;
}
}
}
});
$(data).find('#content .rightside > table [itemprop=description]').each(function () {
dataMap.Synopsis = this.innerHTML;
});
dataMap.Image = $(data).find("#content .leftside a > img").attr('data-src');
table.innerHTML = displayAnimeInfo(animeid);
if (mal.modern) {
$(table).find('a').each(function () {
$(this).hover(function () {
$(this).css("text-decoration", "underline");
}, function () {
$(this).css("text-decoration", "none");
});
});
}
});
}
function getDataFromOriginalMore(preData, animeid) {
var dataMap = store.get(animeid + 'MAP');
// Time Spent Watching
var start = preData.indexOf('Time Spent Watching');
var end = preData.indexOf('<small>(');
dataMap.TimeSpentWatching = preData.substring(start + 21, end);
start = end;
end = preData.indexOf('per episode');
var episodeTime = preData.substring(start + 8, end);
dataMap.EpisodeTime = episodeTime;
}
//--------------------------------//
//     Display Data Functions     //
//--------------------------------//
function displayTable(animeid, tdtype, moreObject, memberId) {
return function () {
var table = $(moreObject).find('.td' + tdtype + '.borderRBL')[0];
if (table && moreObject.hasClass("extraLoaded")) {
if (moreObject.hasClass("extraShowing")) {
table.innerHTML = store.get(animeid + 'Original');
moreObject.toggleClass("extraShowing originalShowing");
} else if (moreObject.hasClass("originalShowing")) {
moreObject.removeClass("originalShowing");
moreObject.hide();
} else {
table.innerHTML = displayAnimeInfo(animeid);
moreObject.addClass("extraShowing");
moreObject.show();
}
} else {
$.post("/includes/ajax-no-auth.inc.php?t=6", { color: tdtype, id: animeid, memId: memberId, type: mal.type[0] }, function (data) {
if (mal.modern) {
moreObject.find(".more-content").html(data.html);
} else {
moreObject.html(data.html);
}
moreObject.show();
moreObject.addClass("extraLoaded extraShowing");
var table = $(moreObject).find('.td' + tdtype + '.borderRBL')[0];
var dataMap = {};
store.set(animeid + 'MAP', dataMap);
store.set(animeid + 'Original', table.innerHTML);
if (table !== null && mal.type[0] != "manga") {
getDataFromOriginalMore(table.innerHTML, animeid);
table.innerHTML = "Fetching data";
getAnimeInfo(animeid, table);
} else if (table !== null) {
table.innerHTML = "Fetching data";
getAnimeInfo(animeid, table);
}
}, "json");
}
};
}
function getDataValue(animeid, key) {
var dataMap = store.get(animeid + 'MAP');
return dataMap[key] || "Unavailable";
}
function getDataValues(animeid, key1, key2) {
var dataMap = store.get(animeid + 'MAP');
return dataMap[key1] || dataMap[key2] || "Unavailable";
}
function calcTimeNeeded(episodeTime, totalEpisodes) {
if (totalEpisodes.trim() == "0" || totalEpisodes == "Unknown") {
return 'Unknown';
} else if (episodeTime.indexOf("0 hours, 0 minutes, and 0 seconds") > -1) {
return 'Unknown';
} else if (totalEpisodes.trim() == "1") {
return episodeTime;
} else {
var str = episodeTime.split(' ');
var totalSeconds = parseInt(str[5]) * totalEpisodes + (parseInt(str[2]) * totalEpisodes * 60) + (parseInt(str[0]) * totalEpisodes * 60 * 60);
var seconds = totalSeconds % 60;
var totalMinutes = Math.floor(totalSeconds / 60);
var minutes = totalMinutes % 60;
var hours = Math.floor(totalMinutes / 60);
return hours + " hours, " + minutes + " minutes and " + seconds + " seconds";
}
}
function displayAnimeInfo(animeid) {
var episodes = getDataValue(animeid, 'Episodes');
var chapters = getDataValue(animeid, 'Chapters');
var volumes = getDataValue(animeid, 'Volumes');
var image = getDataValue(animeid, "Image");
var genres = getDataValues(animeid, 'Genre', 'Genres');
var status = getDataValue(animeid, 'Status');
var broadcast = getDataValue(animeid, 'Broadcast');
var score = getDataValue(animeid, 'Score');
var rank = getDataValue(animeid, 'Ranked');
var popularity = getDataValue(animeid, 'Popularity');
var studio = getDataValues(animeid, 'Studio', 'Studios');
var source = getDataValue(animeid, 'Source');
var premiered = getDataValue(animeid, 'Premiered');
var aired = getDataValue(animeid, 'Aired');
var published = getDataValue(animeid, 'Published');
var type = getDataValue(animeid, 'Type');
var demographic = getDataValues(animeid, 'Demographic', 'Demographics');
var themes = getDataValues(animeid, 'Theme', 'Themes');
var synopsis = getDataValue(animeid, 'Synopsis').replace(/\(Source.*[\s\S]*/g, "").replace(/\[.*\]/g, "").replace(/(<br>|\s+)*$/, "");
var timeSpentWatching;
var timeNeeded;
if (mal.type[0] == "anime") {
timeSpentWatching = getDataValue(animeid, 'TimeSpentWatching').replace("tes,", "tes");
timeNeeded = '0';
if (timeSpentWatching.indexOf("0 hours, 0 minutes and 0 seconds") > -1) {
timeNeeded = calcTimeNeeded(getDataValue(animeid, 'EpisodeTime'), episodes);
}
}
return `
<style>
.container {  display: grid;
grid-template-columns: auto 1fr 1fr;
grid-template-rows: min-content 1fr min-content;
gap: 5px;
grid-auto-flow: row;
grid-template-areas:
"image details genres"
"image synopsis synopsis"
"image discuss time";
}
.image { grid-area: image; }
.details { grid-area: details; }
.genres { grid-area: genres; text-align: right; }
.synopsis { grid-area: synopsis; padding: 5px 0; }
.discuss { grid-area: discuss; }
.time { grid-area: time; text-align: right; }
</style>
<div class="container">
<div class="image">
<img src="${image}">
</div>
<div class="details">
${(mal.type[0] == "anime") ? ("<b>Source: <\/b>" + source + "<br>") : ("<b>Type: <\/b>" + type + "<br>")}
${(status.indexOf("Currently Airing") > -1) ? ("<b>Broadcast: <\/b>" + broadcast + "<br>") : ("")}
${(mal.type[0] == "anime") ? ("<b>Episodes: <\/b>" + episodes + "<br>") : ("<b>Volumes: <\/b>" + volumes + "<br><b>Chapters: <\/b>" + chapters + "<br>")}
<b>Score: </b>${score}<br>
${(studio.indexOf("add some") == -1 && mal.type[0] != "manga") ? ("<b>Studio: <\/b>" + studio + "<br>") : ("")}
${(mal.type[0] == "anime") ? (premiered != "Unavailable" ? ("<b>Premiered: <\/b>" + premiered + "<br>") : ("")) : ("")}
${(mal.type[0] == "anime") ? ("<b>Aired: <\/b>" + aired + "<br>") : ("<b>Published: <\/b>" + published + "<br>")}
${(themes !== "Unavailable") ? ("<b>Themes: <\/b>" + themes + "<br>") : ("")}
${(demographic !== "Unavailable") ? ("<b>Demographic: <\/b>" + demographic + "<br>") : ("")}
</div>
<div class="genres">${genres}</div>
<div class="synopsis">${synopsis}</div>
<div class="discuss">
<a href="/forum/?${mal.type[0]}id=${animeid}" target="_blank">
<small>Discuss ${mal.type[0].charAt(0).toUpperCase() + mal.type[0].slice(1)}</small>
</a>
</div>
<div class="time">
${(mal.type[0] == "anime") ? ("<small>" + (timeNeeded == '0' ? ("<b>Time Spent Watching: <\/b>" + timeSpentWatching) : ("<b>Time To Complete: <\/b>" + timeNeeded)) + "<\/small><\/td>") : ("")}
</div>
</div>
`;
}
})(jQuery);