您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
If you constantly need to add an "Other..." type of role instead of the ones in the pre-approved list, this script will add those other roles automatically to the dropdown
// ==UserScript== // @name LibraryThing custom author roles // @namespace https://greasyfork.org/en/users/11592-max-starkenburg // @description If you constantly need to add an "Other..." type of role instead of the ones in the pre-approved list, this script will add those other roles automatically to the dropdown // @include http*://*librarything.tld/work/* // @include http*://*librarything.com/work/* // @include http*://*librarything.tld/addnew.php* // @include http*://*librarything.com/addnew.php* // @version 5 // @grant none // ==/UserScript== // Make a comma-separated list of "Other" role types you'd like to be in the dropdown menu by default var customRolesString = "Ghostwriter, Corporate author, Compiler, Interviewee, Penciller, Letterer, Inker, Colorist, Director, Producer, Actor, Performer"; var suppressRolesString = ""; // If you've made edits to the list of custom or suppressed roles, get those instead if (localStorage.LTcustomRoles) customRolesString = localStorage.LTcustomRoles; if (localStorage.LTsuppressRoles) suppressRolesString = localStorage.LTsuppressRoles; // Make any array of the custom roles, and deal with certain special characters, extra spaces/commas, etc. var customRoles = makeRolesArray(customRolesString); var suppressRoles = makeRolesArray(suppressRolesString); function makeRolesArray(rolesString) { if (rolesString == null || rolesString.trim() == "") { return []; } else { rolesArray = rolesString .replace(/&/g, "&") // escape ampersands (though LT sometimes chokes on these anyway) .replace(/\"/g, """) // escape double quotes .replace(/</g, "<") // escape less thans (though LT sometimes chokes on these anyway) .replace(/>/, ">") // escape greater thans .trim() // remove exterior leading/trailing spaces .split(/\s*,+\s*/); // split with comma delimiter, plus removing leading/trailing spaces on each piece return rolesArray; } } // When focusing (clicking) or arrowing through (keydown) a dropdown menun, add your custom roles to it. // Had to put it on "body" because the menus in the "Add/edit other authors" of the work page are dynamically added. jQuery("body").on("focus keydown", "#bookedit_roles select, #bookedit_authorunflip select, .editotherauthorstable select", function(evt) { // Don't bother to run the below code if it's already been done for this <select> if (!jQuery(this).hasClass("gm-custom-roles-select")) { // For certain things we need to know whether we're editing our book, or setting authors on the whole work var pageType = jQuery(this).closest("#bookedit_roles, #bookedit_authorunflip").length ? "book" : "work"; // Remember the "selected" element, in order to put the selection property back after the sort selectedOpt = jQuery(this).children(":selected"); selected = { val: selectedOpt.attr("value"), text: selectedOpt.text() }; // Get the existing roles from the <select><option> texts (not value, since some don't reflect the text) var existingRoles = jQuery(this).children("option"); // Remove any empty strings from customRoles and suppressRoles for ( var i=0; i<customRoles.length; i++ ) { if ( customRoles[i] == '') delete customRoles[i]; // Remove any custom roles that are already in the list for ( var j=0; j<existingRoles.length; j++ ) { if (customRoles[i] == existingRoles.eq(j).text()) { delete customRoles[i]; } } } for ( var k=0; k<suppressRoles.length; k++ ) { if (suppressRoles[k] == '') delete suppressRoles[k]; } // Move away any that have been added to the suppression list, unless it was "selected" var suppressedSelect = jQuery("#gm-suppressed-select"); if (!suppressedSelect.length) { // Make a hidden select to store away the values of suppressed roles suppressedSelect = jQuery('<select id="gm-suppressed-select" class="gm-suppressed-select-empty"></select>'); suppressedSelect.appendTo("body").hide(); } for ( var l=0; l<suppressRoles.length; l++ ) { for ( var m=0; m<existingRoles.length; m++) { if (suppressRoles[l] == existingRoles.eq(m).text()) { if (suppressedSelect.not(".gm-suppressed-select-empty")) { // Just fill it once until such time that the suppressed roles change existingRoles.eq(m).clone().appendTo(suppressedSelect); } if (!existingRoles.eq(m).is(":selected")) { existingRoles.eq(m).remove(); } } } } suppressedSelect.removeClass("gm-suppressed-select-empty"); // Add <option>s for adding custom roles or suppressing standard ones var invalidValue = pageType == "book" ? "" : "-1"; // The value of invalid options depends on their location var lineBeforeOther; if (pageType == "book") { lineBeforeOther = jQuery(this).children("option[value='xxxOTHERxxx']").prev(); } else { lineBeforeOther = jQuery(this).children("option[value='-1']").eq(-2); } lineBeforeOther.before('<option value="' + invalidValue + '" class="gm-custom-roles-option gm-custom-roles-line">--------------</option>'); lineBeforeOther.before('<option value="' + invalidValue + '" class="gm-custom-roles-option gm-edit-custom-roles">Add custom roles...</option>'); lineBeforeOther.before('<option value="' + invalidValue + '" class="gm-custom-roles-option gm-suppress-standard-roles">Suppress standard roles...</option>'); // Add <option>s for each of the new custom roles for ( var n=0; n<customRoles.length; n++ ) { if (customRoles[n] !== undefined) { jQuery(this).append('<option value="' + customRoles[n] + '" class="gm-custom-roles-option">' + customRoles[n] + '</option>'); } } // Sort the custom and standard roles alphabetically // Thanks to SolutionYogi at http://stackoverflow.com/a/1134983/752122 var roleOptions = jQuery(this).children("option:eq(1)").nextUntil(".gm-custom-roles-option"); // The ones that were already in the list before "Other ..." roleOptions = roleOptions.add(lineBeforeOther.next().nextAll()); // The ones that have been added after "Other ..." roleOptions = roleOptions.get().sort(function(a, b) { return jQuery(a).text().localeCompare(jQuery(b).text()); }); jQuery(this).children("option:eq(1)").after(roleOptions); // Set the selected option again after this list has been rearranged var options = jQuery(this).children("option"); var newSelectedIndex = 0; for(var o=0; o<options.length; o++) { currentOpt = options.eq(o); if (currentOpt.attr("value") == selected.val && currentOpt.text() == selected.text) { newSelectedIndex = o; break; } } jQuery(this).get(0).selectedIndex = newSelectedIndex; // Mark this <select> as processed so that we're not running all the above code on each and every focus/keydown jQuery(this).addClass("gm-custom-roles-select"); } }); // Edit the roles to whatever you want jQuery("body").on("change", "#bookedit_roles select, #bookedit_authorunflip select, .editotherauthorstable select", function(evt) { var selected = jQuery(this).children(":selected"); // console.log(jQuery(this).children().last().text()); // Add new custom roles if (selected.hasClass("gm-edit-custom-roles") ) { var editRoles = prompt("Change which custom roles you would like to be appear in the dropdown (comma-separated)",customRolesString); if (editRoles != null) { // Store the user's preferred roles in localStorage (and reset customRoles[String] too) localStorage.LTcustomRoles = customRolesString = editRoles; customRoles = makeRolesArray(editRoles); resetSelects(jQuery(this)); } // Or suppress the existing ones } else if (selected.hasClass("gm-suppress-standard-roles") ) { var editSuppressRoles = prompt("Enter a comma-separated list of the roles you never use, e.g. Afterword, Narrator, etc.",suppressRolesString); if (editSuppressRoles != null) { // Store the user's suppressed roles in localStorage (and reset suppressRoles[String] too) localStorage.LTsuppressRoles = suppressRolesString = editSuppressRoles; suppressRoles = makeRolesArray(editSuppressRoles); resetSelects(jQuery(this)); } } }); // Reset the lists that had been previously processed so that they can get any updates ... function resetSelects(select) { select.blur(); jQuery(".gm-custom-roles-option") .not(":selected") // excluding custom <option>s that were already selected (don't want to undo previous work) .add(".gm-custom-roles-line, .gm-edit-custom-roles, .gm-suppress-standard-roles") // unless it was "Add/suppress roles ..." (such a selection doesn't need to be preserved) .remove(); jQuery(".gm-custom-roles-select").append(jQuery("#gm-suppressed-select").children().clone()); jQuery("#gm-suppressed-select").remove(); jQuery(".gm-custom-roles-select").removeClass("gm-custom-roles-select"); }