您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Mass-select tags in the Unfilterable or Unwrangleable bin to move into the other bin
当前为
// ==UserScript== // @name AO3 [Wrangling]: Mass-Unwrangleable // @namespace https://gf.qytechs.cn/en/users/906106-escctrl // @description Mass-select tags in the Unfilterable or Unwrangleable bin to move into the other bin // @author escctrl // @version 1.0 // @match *://*.archiveofourown.org/tags/*/wrangle?* // @require https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js // @license MIT // ==/UserScript== (function($) { 'use strict'; const binParams = new URLSearchParams(window.location.search); const binStatus = binParams.has('status') ? binParams.get('status') : ""; // don't proceed with the rest of the script if we're not on an unfilterable or unwrangleable bin if (binStatus != "unfilterable" && binStatus != "unwrangleable") { return false; } // build the additional button to mass-set to unwrangleable // in an unwrangleable bin, the label says to deselect the unwrangleable status const mass_label = (binStatus == "unwrangleable") ? "Remove Unwrangleable flag" : "Set Unwrangleable flag"; const mass_button = '<button name="wrangle_unwrangleable" style="padding-left: 0.75em;">' + mass_label + '</button> '; $('#wrangulator p.submit.actions').prepend(mass_button); // helper vars const errorMsg = []; var completeTags = 0; var selectedTags = []; // add the event listener to the button with function to load the Edit pages $('button[name="wrangle_unwrangleable"]').click(function(e) { // stop button from automatically submitting the form it's in e.preventDefault(); // grab the selected tags selectedTags = array($('input[name="selected_tags[]"]')).filter(inp => inp.checked); if (selectedTags.length < 1) { alert("Please select at least one tag!"); return false; } // now let's run through all the tags and update them $(selectedTags).each(function(i, tag) { var url = $(tag).closest('tr').find('a[href$="/edit"]')[0]; // nifty jQuery, will work with icon action buttons and without url = url.href; // jQuery would return the relative URL, but we need the absolute const tagFrame = document.createElement("iframe"); // create the iframe, hide it, add it to the DOM, and attach an event listener to make make the checkbox changes // we're routing through: the iFrame we're operating in, and the index of the tag that's being changed $(tagFrame).hide().appendTo('body').one('load', function() { bgEditLoad(tagFrame, i); }); // .one() runs only once and removes itself tagFrame.src = url; }); }); // event listener function to do the actual Edit page changes in the iframe function bgEditLoad(tagFrame, iTag) { // need to pick up on ao3jail. since the load event always triggers on iFrames, and HTTP responses are impossible to get a hold of, we'll just look at the page content... if ($(tagFrame).contents().find('#edit_tag').length != 1) { errorMsg[iTag] = "Page could not load. Retry later"; // manually trigger the event function to do the rest of the work bgEditSubmit(tagFrame, iTag); return; } // switch the state of the unwranglable checkbox in the iframe const fieldUnwrangleable = $(tagFrame).contents().find('#tag_unwrangleable')[0]; fieldUnwrangleable.checked = fieldUnwrangleable.checked == true ? false : true; // add another event listener to retrieve the fail/success message, and submit the iframe $(tagFrame).one('load', function() { bgEditSubmit(tagFrame, iTag); }); $(tagFrame).contents().find('#edit_tag')[0].submit(); } // event listener function to catch errors occurring in the iframe after submitting the form function bgEditSubmit(tagFrame, iTag) { // need to pick up on ao3jail. since the load event always triggers on iFrames, and HTTP responses are impossible to get a hold of, we'll just look at the page content... if ($(tagFrame).contents().find('#edit_tag').length != 1) { errorMsg[iTag] = "Page could not load. Retry later"; } // tracking any errors we've run into else { const err = $(tagFrame).contents().find('#error'); if (err.length > 0) { errorMsg[iTag] = err[0].innerHTML; } } document.body.removeChild(tagFrame); // if this was the last tag, we can write out errors on the bin's page // note: there are no iframes open anymore completeTags++; if (completeTags == selectedTags.length) { finish(); } } // write out all errors that occurred and all tags that were changed successfully function finish() { const successMsg = []; const failMsg = []; $(selectedTags).each(function(i, tag) { var tagRow = $(tag).closest('tr'); var tagURL = $(tagRow).find('a[href$="/edit"]')[0]; tagURL = tagURL.href; var tagName = $(tagRow).find('th label')[0]; tagName = tagName.innerText; // errorMsg[] has the corresponding indices so we know which tag failed if (errorMsg[i] != undefined) { failMsg.push('<a href="' + tagURL + '">' + tagName + '</a>: ' + errorMsg[i]); } else { successMsg.push('<a href="' + tagURL + '">' + tagName + '</a>'); // remove the changed tags from the bin page $(tagRow).remove(); } }); // constructing the response message to the user and showing it if (failMsg.length > 0) { const fail = '<div id="error" class="error">The following tags\' Unwrangleable flag could not be updated:<br />' + failMsg.join('<br />') + '</div>'; $(fail).prependTo('#main'); window.scrollTo(0,0); } if (successMsg.length > 0) { const success = 'The following tags\' Unwrangleable flag was updated successfully:<br />' + successMsg.join(', '); $('.flash').clone().prependTo('#main').addClass('notice').html(success); window.scrollTo(0,0); } } // the return value of document.querySelectorAll is technically a "NodeList", which can be indexed like an array, but // doesn't have helpful functions like .map() or .forEach(). So this is a simple helper function to turn a NodeList // (or any other array-like object (indexed by integers starting at zero)) into an array const array = a => Array.prototype.slice.call(a, 0); })(jQuery);
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址