您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Allows to find missing relations and entries with wrong chapter/episode count.
当前为
// ==UserScript== // @name MyAnimeList (MAL) Track Missing Relations // @namespace https://greasyfork.org/users/7517 // @description Allows to find missing relations and entries with wrong chapter/episode count. // @icon http://i.imgur.com/b7Fw8oH.png // @version 6.6.4 // @author akarin // @include /^http:\/\/myanimelist\.net\/profile/ // @grant none // @noframes // ==/UserScript== /*jslint fudge, maxerr: 10, browser, devel, this, white, for */ /*global jQuery */ (function($) { "use strict"; // Status codes used by MAL API var USER_STATUS = { IN_PROCESS: 1, COMPLETED: 2, ON_HOLD: 3, DROPPED: 4, PLAN_TO: 6 }; var SERIES_STATUS = { IN_PROCESS: 1, COMPLETED: 2, NOT_YET: 3 }; // Main object var mal = { version: '6.5', // cache name: '', // username type: '' // anime or manga }; mal.settings = { ajax: { delay: 300, timeout: 10000 }, width: 670, height: 765, // Predefined data lists: availableRelations: [ 'Alternative Setting', 'Alternative Version', 'Character', 'Full Story', 'Other', 'Parent Story', 'Prequel', 'Sequel', 'Side Story', 'Spin-off', 'Summary' ], availableStatus: { anime: ['Watching', 'Completed', 'On-Hold', 'Dropped', 'Plan to Watch'], manga: ['Reading', 'Completed', 'On-Hold', 'Dropped', 'Plan to Read'] }, // User settings: excludedRelations: [], excludedStatus: { anime: [], manga: [] }, fullScan: { anime: false, manga: false }, load: function() { mal.settings.excludedRelations = ['Adaptation']; mal.settings.availableRelations.forEach(function(val) { var id = 'mr_x' + mal.type[0] + '_' + val.toHtmlId(); if (mal.loadSetting(id, 'false') !== 'false') { mal.settings.excludedRelations.push(val); } }); ['anime', 'manga'].forEach(function(status) { mal.settings.excludedStatus[status] = ['Empty Status']; mal.settings.availableStatus[status].forEach(function(val) { var id = 'mr_xs' + status[0] + '_' + val.toHtmlId(); if (mal.loadSetting(id, 'false') !== 'false') { mal.settings.excludedStatus[status].push(val); } }); mal.settings.fullScan[status] = mal.loadSetting('mr_xo' + status[0] + '_fullscan', 'false') !== 'false'; }); }, reset: function() { mal.settings.availableRelations.forEach(function(val) { mal.saveSetting('mr_xa_' + val.toHtmlId(), 'false'); mal.saveSetting('mr_xm_' + val.toHtmlId(), 'false'); }); ['anime', 'manga'].forEach(function(status) { mal.settings.availableStatus[status].forEach(function(val) { mal.saveSetting('mr_xs' + status[0] + '_' + val.toHtmlId(), 'false'); }); mal.saveSetting('mr_xo' + status[0] + '_fullscan', 'false'); }); } }; $.fn.myfancybox = function(onstart) { return $(this).click(function() { mal.fancybox.start(onstart); }); }; mal.fancybox = { body: $('<div id="mr_fancybox_inner">'), outer: $('<div id="mr_fancybox_outer">'), wrapper: $('<div id="mr_fancybox_wrapper">'), init: function(el) { mal.fancybox.outer.hide() .append(mal.fancybox.body) .insertAfter(el); mal.fancybox.wrapper.hide() .insertAfter(el); mal.fancybox.wrapper.click(function() { mal.fancybox.close(); }); }, start: function(onstart) { mal.fancybox.body.children().hide(); if (!onstart()) { mal.fancybox.close(); return; } mal.fancybox.wrapper.show(); mal.fancybox.outer.show(); }, close: function() { mal.fancybox.outer.hide(); mal.fancybox.wrapper.hide(); } }; function main() { mal.name = $('.icon-rss + div > a:first').prop('href').match(/&u=(.+)$/)[1].trim(); if (!mal.name.length) { return; } var panel = $('<div id="mr_panel">') .append('<span id="mr_profile"><a href="/profile/' + mal.name + '"><b>' + mal.name + '</b></a></span>') .append(mal.content.status) .prependTo(mal.content.body); var span = $('<span id="mr_links_settings">') .append($('<a href="javascript:void(0);" title="Switch lists" id="mr_link_switch">Manga</a>') .click(function() { var type = mal.type === 'anime' ? 'manga' : 'anime'; mal.fancybox.close(); $('div.floatRightHeader > a[id^="mr_link_' + type + '"]').trigger('click'); return true; }) ) .append(' - ') .append($('<a href="javascript:void(0);" title="Change calculation settings">Settings</a>') .myfancybox(function() { mal.content.updateSettings(); return true; }) ) .append(' - ') .append($('<a href="javascript:void(0);" title="Recalculate missing relations">Rescan</a>') .click(function() { if (mal.entries.isUpdating()) { alert('Updating in process!'); } else if (confirm('Recalculate missing relations?')) { mal.entries.update(mal.settings.fullScan[mal.type], false); } }) ) .append(' - ') .append($('<a href="javascript:void(0);" title="Update current missing relations">Update</a>') .click(function() { if (mal.entries.isUpdating()) { alert('Updating in process!'); } else if (confirm('Update current missing relations?')) { mal.entries.update(mal.settings.fullScan[mal.type], true); } }) ); $('<div id="mr_links">') .append(span) .prependTo(panel); var header = $('<h2 id="mr_body_title">Missing Relations</h2>') .prependTo(mal.content.body); mal.fancybox.init('#contentWrapper'); mal.content.body .append(mal.content.list) .appendTo(mal.fancybox.body); mal.content.settings .prepend(header.clone()) .appendTo(mal.fancybox.body); var links = $('<div class="floatRightHeader">') .append('<a href="javascript:void(0);" id="mr_link_anime">Missing Anime Relations</a>') .append(' - ') .append('<a href="javascript:void(0);" id="mr_link_manga">Missing Manga Relations</a>') .prependTo('.container-right > #statistics > h2'); $('a[id^="mr_link_"]', links).each(function() { var type = this.id.match(/^mr_link_(\w+)$/)[1]; $(this).myfancybox(function() { if (type !== mal.type) { if (!mal.entries.isUpdating()) { mal.content.status.empty(); } else { alert('Updating in process!'); return false; } } var listType = $('#mr_list_type', mal.content.body); mal.type = type; $('#mr_links_settings > #mr_link_switch', mal.content.body) .text(mal.type === 'anime' ? 'Manga' : 'Anime'); if (!listType.length || listType.val() !== mal.type) { mal.settings.load(); mal.entries.load(); mal.content.updateList(false); } mal.content.body.show(); return true; }); }); } mal.entries = { // Cache data: left: {}, graph: {}, title: {}, wrong: {}, hidden: {}, ignored: {}, // Progress data: total: 0, done: 0, fail: 0, skip: 0, load: function() { mal.entries.clear(); mal.entries.left = mal.loadValue('mal.entries.left', mal.entries.left); mal.entries.graph = mal.loadValue('mal.entries.graph', mal.entries.graph); mal.entries.title = mal.loadValue('mal.entries.title', mal.entries.title); mal.entries.wrong = mal.loadValue('mal.entries.wrong', mal.entries.wrong); mal.entries.ignored = mal.loadValue('mal.entries.ignored', mal.entries.ignored); mal.entries.hidden = mal.loadValue('mal.entries.hidden', mal.entries.hidden); }, save: function() { mal.saveValue('mal.entries.left', mal.entries.left); mal.saveValue('mal.entries.graph', mal.entries.graph); mal.saveValue('mal.entries.title', mal.entries.title); mal.saveValue('mal.entries.wrong', mal.entries.wrong); mal.saveValue('mal.entries.ignored', mal.entries.ignored); mal.entries.saveHidden(); }, saveHidden: function() { mal.saveValue('mal.entries.hidden', mal.entries.hidden); }, clear: function() { mal.entries.total = 0; mal.entries.done = 0; mal.entries.fail = 0; mal.entries.skip = 0; mal.entries.left = {}; mal.entries.graph = {}; mal.entries.title = {}; mal.entries.wrong = {}; mal.entries.ignored = {}; }, clearHidden: function() { mal.entries.hidden = {}; }, isUpdating: function() { return (mal.entries.done + mal.entries.fail + mal.entries.skip) < mal.entries.total; }, update: function(fullScan, onlyNew) { var userlist = []; var right = {}; if (!mal.entries.isUpdating()) { mal.content.status.text(' - Loading...'); if (!onlyNew) { mal.entries.clear(); } else { mal.entries.wrong = {}; mal.entries.ignored = {}; } mal.settings.load(); loadUserList(); } function loadUserList() { var statusRe = new RegExp('^(' + mal.settings.excludedStatus[mal.type].join('|') + ')$', 'i'); $.get('/malappinfo.php?u=' + mal.name + '&status=all&type=' + mal.type, function(data) { $(mal.type, data).each(function() { var id = $('series_' + mal.type + 'db_id', this).text().trim(); var title = $('series_title', this).text().toHtmlStr(); var status = $('series_status', this).text().trim(); var episodes = parseInt($('series_episodes', this).text().trim() || '0'); var chapters = parseInt($('series_chapters', this).text().trim() || '0'); var volumes = parseInt($('series_volumes', this).text().trim() || '0'); var userStatus = $('my_status', this).text().trim(); var userEpisodes = parseInt($('my_watched_episodes', this).text().trim() || '0'); var userChapters = parseInt($('my_read_chapters', this).text().trim() || '0'); var userVolumes = parseInt($('my_read_volumes', this).text().trim() || '0'); //my_rereadingg is not an error !!! var rewatching = $(mal.type === 'anime' ? 'my_rewatching' : 'my_rereadingg', this).text().trim() || '0'; var entry = { id: parseInt(id), title: title, status: mal.settings.availableStatus[mal.type][ userStatus - (userStatus == USER_STATUS.PLAN_TO ? 2 : 1) ], isCorrect: !( (userStatus != USER_STATUS.PLAN_TO && status == SERIES_STATUS.NOT_YET) || (userStatus == USER_STATUS.COMPLETED && rewatching == '0' && (status != SERIES_STATUS.COMPLETED || episodes != userEpisodes || chapters != userChapters || volumes != userVolumes)) || (userStatus != USER_STATUS.COMPLETED && status == SERIES_STATUS.COMPLETED && ((episodes > 0 && userEpisodes >= episodes) || (volumes > 0 && userVolumes >= volumes) || (chapters > 0 && userChapters >= chapters))) ) }; if (!entry.isCorrect) { mal.entries.wrong[entry.id] = true; } if (entry.status.match(statusRe)) { mal.entries.ignored[entry.id] = true; } userlist.push(entry); }); loadContinue(); }); } function loadContinue() { if (mal.entries.isUpdating()) { return; } mal.entries.done = 0; mal.entries.fail = 0; mal.entries.skip = 0; mal.entries.total = userlist.length; mal.content.updateStatus(false, null); if (!mal.entries.total) { mal.content.updateList(true); return; } var delay = 0; var timeDelta = 0; var statusRe = new RegExp('^(' + mal.settings.excludedStatus[mal.type].join('|') + ')$', 'i'); userlist.forEach(function(entry) { mal.entries.title[entry.id] = entry.title; if (mal.entries.left.hasOwnProperty(entry.id) || entry.status.match(statusRe)) { mal.entries.skip += 1; mal.content.updateStatus(false, null); mal.content.updateList(true); return; } setTimeout(function() { var timeStart = new Date().getTime(); $.ajax('/' + mal.type + '/' + entry.id) .done(function(data) { timeDelta = (timeDelta + (new Date().getTime()) - timeStart) / 2; mal.entries.left[entry.id] = true; loadRelations(entry.id, data, fullScan); mal.entries.done += 1; mal.content.updateStatus(false, null); if (fullScan) { loadFull(); } else { mal.content.updateList(true); } }) .fail(function() { mal.entries.fail += 1; mal.content.updateStatus(false, null); console.log('Failed: /' + mal.type + '/' + entry.id); if (fullScan) { loadFull(); } else { mal.content.updateList(true); } }); }, delay); delay += mal.settings.ajax.delay; }); } function loadFull() { if (mal.entries.isUpdating()) { return; } var count = 0; $.each(right, function(id) { if (mal.entries.left.hasOwnProperty(id)) { delete right[id]; } else { count += 1; } }); var opt = { done: mal.entries.done, fail: mal.entries.fail, skip: mal.entries.skip, total: mal.entries.total }; mal.entries.done = 0; mal.entries.fail = 0; mal.entries.skip = 0; mal.entries.total = count; mal.content.updateStatus(true, opt); if (!mal.entries.total) { mal.content.updateList(true); return; } var delay = 0; $.each(right, function(id) { setTimeout(function() { $.ajax('/' + mal.type + '/' + id) .done(function(data) { loadRelations(id, data, false); mal.entries.done += 1; mal.content.updateStatus(true, opt); mal.content.updateList(true); }) .fail(function() { mal.entries.fail += 1; mal.content.updateStatus(true, opt); console.log('Failed: /' + mal.type + '/' + id); mal.content.updateList(true); }); }, delay); delay += mal.settings.ajax.delay; }); } function loadRelations(lId, data, addRight) { $('h2 + table[class*="_detail_related_"] tr', data).each(function() { if ($('td:first-child', this).text().match(new RegExp('(' + mal.settings.excludedRelations.join('|') + ')', 'i'))) { return; } $('td:last-child a[href]', this).each(function() { var idData = $(this).prop('href').match(/\d+/); if (!idData) { console.log('Empty Relation: ' + lId); return; } var rId = parseInt(idData[0]); if (!mal.entries.ignored.hasOwnProperty(rId)) { mal.entries.title[rId] = $(this).text().toHtmlStr(); mal.entries.addRelation(lId, rId); if (addRight) { right[rId] = true; } } }); }); } }, addRelation: function(lId, rId) { [ { x: lId, y: rId }, { x: rId, y: lId } ].forEach(function(rel) { if (!mal.entries.graph.hasOwnProperty(rel.x)) { mal.entries.graph[rel.x] = []; } if (mal.entries.graph[rel.x].indexOf(rel.y) < 0) { mal.entries.graph[rel.x].push(rel.y); } }); }, getTitle: function(id) { var result = mal.entries.title.hasOwnProperty(id) ? mal.entries.title[id] : ''; return !result.length ? '?' : result; }, getComps: function() { var result = {}; var used = {}; var comp = []; function dfs(v) { used[v] = true; comp.push(v); if (!mal.entries.graph.hasOwnProperty(v)) { return; } mal.entries.graph[v].forEach(function(to) { if (!used.hasOwnProperty(to)) { dfs(to); } }); } $.each(mal.entries.graph, function(v) { if (!used.hasOwnProperty(v)) { comp = []; dfs(v); if (comp.length > 1) { result[v] = comp; } } }); return result; }, comparator: function(a, b) { var aTitle = mal.entries.getTitle(a).toLowerCase(); var bTitle = mal.entries.getTitle(b).toLowerCase(); return aTitle.localeCompare(bTitle); } }; mal.content = { body: $('<div id="mr_body" class="mr_body">'), settings: $('<div id="mr_settings" class="mr_body"><div class="mr_list" /></div>'), status: $('<span id="mr_status_msg">'), list: $('<div class="mr_list">'), updateStatus: function(extra, opt) { if (!opt) { opt = { done: '', fail: '', skip: '', total: '' }; } mal.content.status.html(' -' + ' Done: <b><span style="color: green;">' + (extra ? (opt.done + '+') : '') + mal.entries.done + '</span></b>' + ' Failed: <b><span style="color: #c32;">' + (extra ? (opt.fail + '+') : '') + mal.entries.fail + '</span></b>' + ' Skipped: <b><span style="color: gray;">' + (extra ? (opt.skip + '+') : '') + mal.entries.skip + '</span></b>' + ' Total: <b>' + (extra ? (opt.total + '+') : '') + mal.entries.total + '</b>' ); }, updateList: function(save) { if (mal.entries.isUpdating()) { return; } if (save) { mal.entries.save(); } $('#mr_body_title', mal.content.body) .text('Missing Relations – ' + (mal.type === 'anime' ? 'Anime' : 'Manga')); var listType = $('<input type="hidden" id="mr_list_type" value="' + mal.type + '">'); var comps = mal.entries.getComps(); var wrong = Object.keys(mal.entries.wrong); if (!Object.keys(comps).length && !wrong.length) { mal.content.list.empty().append('<p id="mr_notfound">No missing relations found.</p>').append(listType); return; } var table = $('<table class="relTable" border="0" cellpadding="0" cellspacing="0" width="100%"><thead><tr><th>You\'ve ' + (mal.type === 'anime' ? 'watched' : 'read') + ' this…</th><th>…so you might want to check this:</th></tr></table>'); var undel = $('<div id="mr_undelete"><p id="mr_undelete_msg" style="display: none;">There are <span id="mr_undelete_num" style="font-weight: bold;" /> hidden relations. <a href="javascript:void(0);" title="Show hidden relations" onclick="window.showHiddenRelations();">Show them</a></p></div>'); var tfoot = $('<tfoot><tr><td class="mr_td_left"><div class="mr_count"><span /></div></td><td class="mr_td_right"><div class="mr_count"><span /></div></td></tr></tfoot>'); // red relations if (wrong.length > 0) { var ul = $('<ul>'); var size = 0; wrong.sort(mal.entries.comparator).forEach(function(id) { mal.content.getLiLeft(id).prop('id', 'mr_li_red_' + id).appendTo(ul); size += 1; }); var tbody_red = $('<tbody>'); var tr_red = $('<tr class="mr_tr_data">') .append($('<td class="mr_td_left">').append(ul)) .append($('<td class="mr_td_right">').append(mal.content.getEntryWarning())) .appendTo(tbody_red); if (size > 5) { tr_red.addClass('mr_tr_collapsed'); $('<tr class="mr_tr_more">').append(mal.content.getMoreLink()).insertAfter(tr_red); } tbody_red.appendTo(table); } // normal relations Object.keys(comps).sort(mal.entries.comparator).forEach(function(key) { var ulLeft = $('<ul>'); var ulRight = $('<ul>'); var lSize = 0; var rSize = 0; comps[key].sort(mal.entries.comparator).forEach(function(id) { if (mal.entries.ignored.hasOwnProperty(id)) { return; } if (mal.entries.left.hasOwnProperty(id)) { mal.content.getLiLeft(id).prop('id', 'mr_li_' + id).appendTo(ulLeft); lSize += 1; } else { mal.content.getLiRight(id).prop('id', 'mr_li_' + id).appendTo(ulRight); rSize += 1; } }); if (lSize > 0 && rSize > 0) { var tbody = $('<tbody>'); var tr = $('<tr class="mr_tr_data">') .append($('<td class="mr_td_left">').append(ulLeft)) .append($('<td class="mr_td_right">').append(ulRight)) .appendTo(tbody); if (lSize > 5 || rSize > 5) { tr.addClass('mr_tr_collapsed'); $('<tr class="mr_tr_more">').append(mal.content.getMoreLink()).insertAfter(tr); } tbody.appendTo(table); } }); mal.content.list.empty() .append(undel) .append(table.append(tfoot)) .append(listType); mal.hideHiddenRelations(true); mal.content.updateLineCount(); }, updateSettings: function() { $('#mr_body_title', mal.content.settings) .text('Missing Relations – Settings'); var tableExclude = $('<table class="relTable" border="0" cellpadding="0" cellspacing="0" width="100%"><thead><tr><th>Exclude Anime Relations:</th><th>Exclude Manga Relations:</th></tr><tbody /></table>'); var tableIgnore = $('<table class="relTable" border="0" cellpadding="0" cellspacing="0" width="100%"><thead><tr><th>Ignore Anime Entries:</th><th>Ignore Manga Entries:</th></tr><tbody /></table>'); var tableOther = $('<table class="relTable" border="0" cellpadding="0" cellspacing="0" width="100%"><thead><tr><th>Other Anime Settings:</th><th>Other Manga Settings:</th></tr><tbody /></table>'); var buttons = $('<div class="mr_buttons">') .append($('<input class="inputButton" value="Save" type="button">').click(function() { $('input[type="checkbox"]', mal.content.settings).each(function() { mal.saveSetting(this.id, $(this).prop('checked').toString()); }); mal.settings.load(); mal.fancybox.start(function() { mal.content.body.show(); return true; }); })) .append($('<input class="inputButton" value="Cancel" type="button">').click(function() { mal.fancybox.start(function() { mal.content.body.show(); return true; }); })) .append($('<input class="inputButton" value="Reset" type="button">').click(function() { if (!confirm('Reset all settings?')) { return; } mal.settings.reset(); mal.settings.load(); mal.fancybox.start(function() { mal.content.body.show(); return true; }); })); // Add exclude relations var tbody = $('tbody', tableExclude); mal.settings.availableRelations.forEach(function(rel) { $('<tr class="mr_tr_data">') .append($('<td class="mr_td_left">') .append(mal.content.getCbSetting(rel, 'mr_xa_' + rel, false))) .append($('<td class="mr_td_right">') .append(mal.content.getCbSetting(rel, 'mr_xm_' + rel, false))) .appendTo(tbody); }); // Add ignore status tbody = $('tbody', tableIgnore); $.each(mal.settings.availableStatus.anime, function(i, statusA) { var statusM = mal.settings.availableStatus.manga[i]; $('<tr class="mr_tr_data">') .append($('<td class="mr_td_left">') .append(mal.content.getCbSetting(statusA, 'mr_xsa_' + statusA, false))) .append($('<td class="mr_td_right">') .append(mal.content.getCbSetting(statusM, 'mr_xsm_' + statusM, false))) .appendTo(tbody); }); // Add other settings tbody = $('tbody', tableOther); $('<tr class="mr_tr_data">') .append($('<td class="mr_td_left">') .append(mal.content.getCbSetting('Deep Scan', 'mr_xoa_fullscan', false))) .append($('<td class="mr_td_right">') .append(mal.content.getCbSetting('Deep Scan', 'mr_xom_fullscan', false))) .appendTo(tbody); var list = $('.mr_list', mal.content.settings).empty() .append(tableExclude) .append(tableIgnore) .append(tableOther); if (!mal.entries.isUpdating()) { list.append(buttons); } else { list.append(buttons.empty() .append('<div id="mr_warning">The settings can\'t be changed during relations calculation!</div>') .append(mal.content.getBtnCancel().val('OK')) ); } mal.content.settings.show(); }, getLiLeft: function(id) { return $('<li>') .append(mal.content.getEntryLink(id, mal.entries.getTitle(id))); }, getLiRight: function(id) { return $('<li>') .append(mal.content.getHideButton('window.hideRelation(' + id + ');', 'Hide this relation')) .append(mal.content.getEntryLink(id, mal.entries.getTitle(id))); }, getCbSetting: function(str, id, state) { id = id.toHtmlId(); state = state.toString(); return $('<div class="mr_checkbox">') .append($('<input name="' + id + '" id="' + id + '" type="checkbox">') .prop('checked', mal.loadSetting(id, state) !== 'false')) .append('<label for="' + id + '">' + str + '</label>'); }, getEntryLink: function(id, title) { return $('<a title="' + title + '"href="' + '/' + mal.type + '/' + id + '" target="_blank">' + title + '</a>'); }, getEntryWarning: function() { return $('<div class="mr_warning"><span>Wrong status or ' + (mal.type === 'anime' ? 'episode' : 'vol./chap.') + ' count</span></div>'); }, getHideButton: function(func, title) { return $('<div class="mr_hide"><span><a href="javascript:void(0);" title="' + title + '" onclick="' + func + '">x</a></span></div>'); }, getMoreLink: function() { var result = $('<td colspan="2">'); $('<a class="mr_more" href="javascript:void(0);">show more</a>').click(function() { var tr = $(this).closest('tr'); tr.prev('.mr_tr_data').removeClass('mr_tr_collapsed'); tr.remove(); }).appendTo(result); return result; }, updateLineCount: function() { $('tfoot td.mr_td_left .mr_count span', mal.content.list).text( 'Total: ' + $('.relTable td.mr_td_left li', mal.content.list).length + ', ' + 'Visible: ' + $('.relTable tbody:not([style*="display: none"]) td.mr_td_left li', mal.content.list).length ); $('tfoot td.mr_td_right .mr_count span', mal.content.list).text( 'Total: ' + $('.relTable td.mr_td_right li', mal.content.list).length + ', ' + 'Visible: ' + $('.relTable td.mr_td_right li:not([style*="display: none"])', mal.content.list).length ); } }; mal.hideRelation = function(id, save) { var li = $('td.mr_td_right li[id="mr_li_' + id + '"]', mal.content.list); if (!li.length) { if (mal.entries.hidden.hasOwnProperty(id)) { delete mal.entries.hidden[id]; } if (save) { mal.entries.saveHidden(); } return; } var row = li.hide().closest('tbody'); var lSize = $('td.mr_td_left li', row).length; var rSize = $('td.mr_td_right li:not([style*="display: none;"])', row).length; row.toggle(rSize > 0); if (lSize <= 5 && rSize <= 5) { $('a.mr_more', row).trigger('click'); } mal.entries.hidden[id] = true; if (save) { mal.entries.saveHidden(); var count = Object.keys(mal.entries.hidden).length; $('#mr_undelete_num', mal.content.list).text(count); $('#mr_undelete_msg', mal.content.list).toggle(count > 0); } }; mal.hideHiddenRelations = function(save) { mal.showHiddenRelations(false); $.each(mal.entries.hidden, function(id) { mal.hideRelation(id, false); }); var count = Object.keys(mal.entries.hidden).length; $('#mr_undelete_num', mal.content.list).text(count); $('#mr_undelete_msg', mal.content.list).toggle(count > 0); if (save) { mal.entries.saveHidden(); } }; mal.showHiddenRelations = function(save) { $('#mr_undelete_msg', mal.content.list).hide(); $('li[id^="mr_li_"]', mal.content.list).show(); $('tbody', mal.content.list).show(); if (save) { mal.entries.clearHidden(); mal.entries.saveHidden(); } }; function encodeKey(key) { return (mal.version + '#' + mal.name + '#' + mal.type + '#' + key); } mal.loadValue = function(key, value) { try { value = JSON.parse(localStorage.getItem(encodeKey(key))) || value; } finally { return value; } }; mal.saveValue = function(key, value) { localStorage.setItem(encodeKey(key), JSON.stringify(value)); }; mal.loadSetting = function(key, value) { try { value = JSON.parse(localStorage.getItem('global#' + key)) || value; } finally { return value; } }; mal.saveSetting = function(key, value) { localStorage.setItem('global#' + key, JSON.stringify(value)); }; window.hideRelation = function(id) { mal.hideRelation(id, true); mal.content.updateLineCount(); }; window.showHiddenRelations = function() { mal.showHiddenRelations(true); mal.content.updateLineCount(); }; String.prototype.toHtmlId = function() { return this.trim().toLowerCase().replace(/\s/g, '_').replace(/[^\w]/g, '_'); }; String.prototype.toHtmlStr = function() { return this.trim().replace(/"/g, '"'); }; $('<style type="text/css">').html( 'div#mr_fancybox_wrapper { position: fixed; width: 100%; height: 100%; top: 0; left: 0; background: rgba(102, 102, 102, 0.3); z-index: 99990; }' + 'div#mr_fancybox_inner { width: ' + mal.settings.width + 'px !important; height: ' + mal.settings.height + 'px !important; overflow: hidden; }' + 'div#mr_fancybox_outer { position: absolute; display: block; width: auto; height: auto; padding: 10px; border-radius: 8px; top: 80px; left: 50%; margin-top: 0 !important; margin-left: ' + (-mal.settings.width/2) + 'px !important; background: #fff; box-shadow: 0 0 15px rgba(32, 32, 32, 0.4); z-index: 99991; }' + 'div.mr_body { text-align: center; width: 100%; height: 100%; padding: 42px 0 0; box-sizing: border-box; }' + 'div#mr_body { padding-top: 65px; }' + 'div.mr_body a, div.mr_body a:visited { color: #1969cb; text-decoration: none; }' + 'div.mr_body a:hover { color: #2d7de0; text-decoration: underline; }' + 'div.mr_body #mr_body_title { position: absolute; top: 10px; left: 10px; width: ' + mal.settings.width + 'px; font-size: 16px; font-weight: normal; text-align: center; margin: 0; border: 0; }' + 'div.mr_body #mr_body_title:after { content: ""; position: absolute; left: 0; bottom: -14px; width: 100%; height: 8px; border-top: 1px solid #eee; background: center bottom no-repeat radial-gradient(#f6f6f6, #fff 70%); background-size: 100% 16px; }' + 'div.mr_body #mr_panel { position: absolute; top: 50px; left: 10px; text-align: left; width: ' + mal.settings.width + 'px; height: 2em; margin: 0 0 1em; }' + 'div.mr_body #mr_links { float: right; }' + 'div.mr_body p#mr_notfound { margin: 10px 0; }' + 'div.mr_body #mr_undelete { background-color: #fff; padding: 0; margin: 0; }' + 'div.mr_body #mr_undelete_msg { margin: 10px 0; font-weight: normal; text-align: center; line-height: 20px; font-size: 13px; }' + 'div.mr_body .mr_list { width: 100%; height: 100%; overflow-x: hidden; overflow-y: auto; margin: 0 auto; border: 1px solid #eee; box-sizing: border-box; }' + 'div.mr_body .relTable { border: none; }' + 'div.mr_body .relTable thead { background-color: #f5f5f5; }' + 'div.mr_body .relTable th { background-color: transparent; width: 50%; padding: 5px 0 5px 6px; font-size: 12px; font-weight: bold; text-align: left; line-height: 20px !important; box-shadow: none; }' + 'div.mr_body .relTable tbody { background-color: #fff; }' + 'div#mr_body .relTable tbody:hover { background-color: #f5f5f5; }' + 'div#mr_body .relTable tbody tr:first-of-type td { box-shadow: 0px 1em 1em -1em #ddd inset; }' + 'div.mr_body .relTable td { background-color: transparent; width: 50%; padding: 5px 0 5px 6px; font-size: 13px; font-weight: normal; text-align: left; line-height: 20px !important; vertical-align: top; }' + 'div.mr_body .relTable td div span { line-height: 20px !important; }' + 'div.mr_body .relTable td ul { list-style-type: none; margin: 0; padding: 0; }' + 'div.mr_body .relTable tr.mr_tr_collapsed td ul { height: 100px; overflow-y: hidden; }' + 'div.mr_body .relTable td ul li { width: 100%; padding: 0; margin: 0; }' + 'div.mr_body .relTable td ul li > a { display: block; width: 295px !important; line-height: 20px !important; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }' + 'div.mr_body .relTable td.mr_td_left ul li > a { width: 310px !important; }' + 'div.mr_body .relTable tfoot td { border-top: 1px solid #f5f5f5; }' + 'div.mr_body .relTable td .mr_count { color: #666; font-size: 11px; font-weight: normal; text-align: left; }' + 'div.mr_body .relTable td .mr_warning { width: 260px; color: #e43; font-size: 12px; font-weight: bold; text-align: left; }' + 'div.mr_body .relTable td .mr_hide { display: inline-block !important; width: 15px; float: right; text-align: left; font-size: 11px; }' + 'div.mr_body .relTable td .mr_hide a { color: #888 !important; line-height: 20px !important; font-style: normal !important; text-decoration: none !important; }' + 'div.mr_body .relTable tr.mr_tr_more td { padding: 0 0 2px 0; }' + 'div.mr_body .relTable td .mr_more { display: block !important; text-align: center; color: #c0c0c0 !important; font-style: normal !important; font-size: 0.9em; text-decoration: none !important; }' + 'div.mr_body .relTable .mr_checkbox > * { vertical-align: middle; }' + 'div.mr_body .relTable .mr_comment { background-color: #f6f6f6; border: 1px solid #ebebeb; font-size: 11px; line-height: 16px; padding: 1px 4px; }' + 'div.mr_body .mr_buttons { position: absolute; bottom: 13px; width: 100%; text-align: center; padding: 5px 10px; box-sizing: border-box; }' + 'div.mr_body .mr_buttons > .inputButton { margin: 2px 5px !important; font-size: 12px; }' + 'div#mr_settings .relTable { margin-bottom: 10px; }' + 'div#mr_settings div#mr_warning { font-weight: bold; text-decoration: underline; margin-bottom: 2px; }' ).appendTo('head'); main(); })(jQuery);