11// ==UserScript==
22// @name Musicbrainz UI enhancements
33// @description Various UI enhancements for Musicbrainz
4- // @version 2026.7.5.5
4+ // @version 2026.7.23.1
55// @downloadURL https://raw.githubusercontent.com/murdos/musicbrainz-userscripts/master/mb_ui_enhancements.user.js
66// @updateURL https://raw.githubusercontent.com/murdos/musicbrainz-userscripts/master/mb_ui_enhancements.user.js
7- // @icon http://wiki.musicbrainz.org/-/ images/3/3d/Musicbrainz_logo.png
7+ // @icon http://wiki.musicbrainz.org/images/3/3d/Musicbrainz_logo.png
88// @namespace http://userscripts.org/users/22504
99// @match https://*musicbrainz.org/*
1010// @match http://*musicbrainz.org/*
@@ -177,6 +177,20 @@ function setRelEditorShortcutsMenu() {
177177}
178178setRelEditorShortcutsMenu ( ) ;
179179
180+ // Set [no label] button: menu command to enable/disable (default disabled)
181+ function setNoLabelButtonMenu ( ) {
182+ if ( typeof GM_registerMenuCommand !== 'function' ) return ;
183+ GM_registerMenuCommand (
184+ `${ GM_getValue ( 'noLabelButtonEnabled' , false ) ? '☑' : '☐' } Set [no label] button` ,
185+ function ( ) {
186+ GM_setValue ( 'noLabelButtonEnabled' , ! GM_getValue ( 'noLabelButtonEnabled' , false ) ) ;
187+ setNoLabelButtonMenu ( ) ;
188+ } ,
189+ { autoClose : false , id : 'noLabelButton' } ,
190+ ) ;
191+ }
192+ setNoLabelButtonMenu ( ) ;
193+
180194$ ( document ) . ready ( function ( ) {
181195 // Follow the instructions found at https://www.last.fm/api/authentication
182196 // then paste your API Key between the single quotes in the variable below.
@@ -192,6 +206,71 @@ $(document).ready(function () {
192206 '<style>.release-title-action-btn { opacity: 0.8; transition: transform 0.15s ease, opacity 0.15s ease; } .release-title-action-btn:hover { opacity: 1; transform: scale(1.15); } .release-title-action-btn:active { transform: scale(1.05); }</style>' ,
193207 ) ;
194208
209+ // Set a release label row to the special [no label] entity and [none] cat. no.
210+ const releaseEditorPageRegex = / ^ \/ r e l e a s e \/ (?: a d d | [ a - f 0 - 9 - ] { 36 } \/ e d i t ) \/ ? $ / i;
211+ if ( releaseEditorPageRegex . test ( window . location . pathname ) && GM_getValue ( 'noLabelButtonEnabled' , false ) ) {
212+ $ ( 'head' ) . append ( `<style>
213+ .mb-ui-set-no-label {
214+ position: absolute;
215+ top: 50%;
216+ left: calc(100% + 16px);
217+ transform: translateY(-50%);
218+ padding: 2px 6px;
219+ border: 1px solid #bbb;
220+ border-radius: 4px;
221+ background: linear-gradient(#fff, #f1f1f1);
222+ color: #444;
223+ font-size: 12px;
224+ line-height: 18px;
225+ white-space: nowrap;
226+ cursor: pointer;
227+ box-shadow: 0 1px 2px rgb(0 0 0 / 10%);
228+ }
229+ .mb-ui-set-no-label:hover,
230+ .mb-ui-set-no-label:focus-visible {
231+ border-color: #888;
232+ background: linear-gradient(#fff, #e7e7e7);
233+ }
234+ .mb-ui-set-no-label:active {
235+ transform: translateY(calc(-50% + 1px));
236+ background: #e3e3e3;
237+ box-shadow: none;
238+ }
239+ .mb-ui-label-row {
240+ position: relative;
241+ }
242+ </style>` ) ;
243+
244+ const setInputValue = function ( input , value ) {
245+ input . value = value ;
246+ input . dispatchEvent ( new InputEvent ( 'input' , { bubbles : true , data : value , inputType : 'insertFromPaste' } ) ) ;
247+ } ;
248+
249+ const addNoLabelButtons = function ( ) {
250+ document . querySelectorAll ( 'input[id^="label-"]' ) . forEach ( function ( labelInput ) {
251+ const row = labelInput . closest ( 'tr' ) ;
252+ const catnoInput = row && row . querySelector ( 'input[id^="catno-"]' ) ;
253+ const removeButton = row && row . querySelector ( '.remove-release-label' ) ;
254+ if ( ! catnoInput || ! removeButton || row . querySelector ( '.mb-ui-set-no-label' ) ) return ;
255+ row . classList . add ( 'mb-ui-label-row' ) ;
256+
257+ const button = document . createElement ( 'button' ) ;
258+ button . type = 'button' ;
259+ button . className = 'mb-ui-set-no-label' ;
260+ button . textContent = '[no label]' ;
261+ button . title = 'Set label to [no label] and catalog number to [none]' ;
262+ button . addEventListener ( 'click' , function ( ) {
263+ setInputValue ( labelInput , '157afde4-4bf5-4039-8ad2-5a15acc85176' ) ;
264+ setInputValue ( catnoInput , '[none]' ) ;
265+ } ) ;
266+ removeButton . insertAdjacentElement ( 'beforebegin' , button ) ;
267+ } ) ;
268+ } ;
269+
270+ addNoLabelButtons ( ) ;
271+ new MutationObserver ( addNoLabelButtons ) . observe ( document . body , { childList : true , subtree : true } ) ;
272+ }
273+
195274 const artistRegex = new RegExp ( 'musicbrainz.org/artist/([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})$' , 'i' ) ;
196275
197276 // Top tracks from Last.fm
0 commit comments