Jump to content

MediaWiki:Gadget-TuneBook.js

Find traditional instrumental music

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
(function ($, mw, OO) {
    "use strict";

    // Carica le librerie OOUI richieste
    mw.loader.using(["oojs-ui-core", "oojs-ui-widgets", "oojs-ui-windows"]).done(function () {
        console.log("✅ TuneBook Selection Gadget loaded with improvements.");

        /********************************************************************
         * 1) Dialog Definition: TuneBookSelectionDialog
         ********************************************************************/
        function TuneBookSelectionDialog(config) {
            TuneBookSelectionDialog.super.call(this, config);
        }
        OO.inheritClass(TuneBookSelectionDialog, OO.ui.ProcessDialog);

        TuneBookSelectionDialog.static.name = 'tunebookSelectionDialog';
        TuneBookSelectionDialog.static.title = 'Collect Sheet Music for your TuneBook';
        // Se vuoi una dimensione dinamica, override getBodyHeight:
        TuneBookSelectionDialog.prototype.getBodyHeight = function () {
           return 600; // Altezza fissa (modifica se necessario)
        };

        TuneBookSelectionDialog.static.actions = [
            { action: 'cancel', label: 'Cancel', flags: 'safe' },
            { action: 'accept', label: 'Copy selected', flags: ['primary', 'progressive'] }
        ];

        TuneBookSelectionDialog.prototype.initialize = function () {
            TuneBookSelectionDialog.super.prototype.initialize.call(this);
            this.content = new OO.ui.PanelLayout({
                padded: true,
                expanded: false,
                scrollable: true
            });
            this.content.$element.css('min-height', '600px');
            this.$body.append(this.content.$element);

            // Array per memorizzare i blocchi ABC e le relative checkbox
            this.abcBlocks = [];
            this.checkboxes = [];

            // Mostra un messaggio di caricamento
            this.content.$element.append($('<p>').text('Loading ABC blocks…'));

            // Avvia il recupero ed il parsing dei blocchi ABC
            this.retrieveAndParseABCBlocks();
        };

        TuneBookSelectionDialog.prototype.retrieveAndParseABCBlocks = function () {
            var dialog = this;
            var currentPage = mw.config.get('wgPageName');
            var api = new mw.Api();
            console.log("Retrieving wikitext for page:", currentPage);

            api.get({
                action: 'query',
                prop: 'revisions',
                titles: currentPage,
                rvprop: 'content',
                formatversion: 2
            }).done(function (data) {
                console.log("Wikitext data received:", data);
                if (data.query.pages && data.query.pages.length) {
                    var page = data.query.pages[0];
                    if (!page.revisions || !page.revisions.length) {
                        dialog.content.$element.empty().append($('<p>').text('No content found.'));
                        return;
                    }
                    var content = page.revisions[0].content;
                    console.log("Wikitext content:", content);

                    // Usa la regexp per estrarre i blocchi ABC
                    var blocks = parseAllABCBlocks(content);
                    console.log("Parsed ABC blocks:", blocks);
                    if (!blocks.length) {
                        dialog.content.$element.empty().append($('<p>').text('No ABC blocks found.'));
                        return;
                    }
                    dialog.abcBlocks = blocks;
                    dialog.buildCheckboxList();
                }
            }).fail(function (err) {
                console.error("Error retrieving wikitext:", err);
                dialog.content.$element.empty().append($('<p>').text('Error retrieving content.'));
            });
        };

        /**
         * Estrae tutti i blocchi ABC dal wikitext, ignorando quelli vuoti o senza "X:".
         */
        function parseAllABCBlocks(content) {
            var blocks = [];
            var regex = /<section\s+begin\s*=\s*[^>]+\/>\s*([\s\S]*?)\s*<section\s+end\s*=\s*[^>]+\/?>/gi;
            var match;
            while ((match = regex.exec(content)) !== null) {
                var rawBlock = match[1].trim();
                if (!rawBlock || !rawBlock.match(/X:/)) {
                    continue;
                }
                blocks.push(rawBlock);
            }
            return blocks;
        }

        TuneBookSelectionDialog.prototype.buildCheckboxList = function () {
            var dialog = this;
            this.content.$element.empty();
            this.content.$element.append($('<p>').text('Select the tune you want to add to your TuneBook:'));

            this.abcBlocks.forEach(function (block, index) {
                // Tenta di estrarre una riga titolo (prima riga "T:")
                var titleMatch = block.match(/^\s*T:\s*(.+)$/m);
                var title = titleMatch ? titleMatch[1].trim() : "Block " + (index + 1);

                var checkbox = new OO.ui.CheckboxInputWidget({ selected: true });
                var field = new OO.ui.FieldLayout(checkbox, {
                    label: title,
                    align: 'inline'
                });
                dialog.content.$element.append(field.$element);
                dialog.checkboxes.push({ checkbox: checkbox, block: block });
            });
        };

        TuneBookSelectionDialog.prototype.onOpen = function () {
            TuneBookSelectionDialog.super.prototype.onOpen.call(this);
            if (this.checkboxes.length === 0) {
                this.$actionArea.find('button[data-action="accept"]').prop('disabled', true);
            }
        };

        // Modifica: al click su "accept", prima di copiare i blocchi, verifica/crea la pagina nel namespace dell'utente
        TuneBookSelectionDialog.prototype.getActionProcess = function (action) {
            var dialog = this;
            if (action === 'accept') {
                return new OO.ui.Process(function () {
                    var selectedBlocks = dialog.checkboxes
                        .filter(function (item) { return item.checkbox.isSelected(); })
                        .map(function (item) { return item.block; });
                    console.log("Selected ABC blocks:", selectedBlocks);
                    if (selectedBlocks.length === 0) {
                        dialog.close({ action: action });
                        return;
                    }
                    // Verifica e, se necessario, crea la pagina TuneBook, poi copia i blocchi selezionati
                    ensureTuneBookPage(function(tuneBookTitle) {
                        copyBlocksToTuneBook(selectedBlocks, tuneBookTitle);
                    });
                    dialog.close({ action: action });
                });
            } else if (action === 'cancel') {
                return new OO.ui.Process(function () {
                    console.log("Dialog cancelled.");
                    dialog.close({ action: action });
                });
            }
            return TuneBookSelectionDialog.super.prototype.getActionProcess.call(this, action);
        };

        /**
         * Verifica se esiste la pagina TuneBook dell'utente (User:SafeUsername/TuneBook).
         * Se non esiste, la crea inserendo un testo iniziale (più newline).
         * Una volta completato, richiama il callback con il titolo della pagina.
         */
        function ensureTuneBookPage(callback) {
            var api = new mw.Api();
            var username = mw.config.get('wgUserName');
            if (!username) {
                alert("You must be logged in to use this feature.");
                return;
            }
            var safeUsername = username.replace(/\s+/g, '_');
            var tuneBookTitle = 'User:' + safeUsername + '/TuneBook';

            api.get({
                action: 'query',
                titles: tuneBookTitle,
                formatversion: 2
            }).done(function(data) {
                var page = data.query.pages[0];
                if (page.missing !== undefined) {
                    if (confirm("The page " + tuneBookTitle + " does not exist. Do you want to create it?")) {
                        // Testo iniziale da inserire nella pagina appena creata
                        var initialText = "The Traditional Tune Archive TuneBook creation system\n\n";
                        api.postWithToken('csrf', {
                            action: 'edit',
                            title: tuneBookTitle,
                            text: initialText,
                            summary: 'Automatically creating TuneBook page'
                        }).done(function(result) {
                            if (result.edit && result.edit.result === 'Success') {
                                callback(tuneBookTitle);
                            } else {
                                alert("Error creating TuneBook page.");
                            }
                        }).fail(function(err) {
                            console.error("Error creating TuneBook page:", err);
                            alert("Error creating TuneBook page.");
                        });
                    } else {
                        alert("Operation cancelled.");
                    }
                } else {
                    // La pagina esiste già
                    callback(tuneBookTitle);
                }
            }).fail(function(err) {
                console.error("Error checking TuneBook page:", err);
                alert("Error checking TuneBook page.");
            });
        }

        /**
         * Copia i blocchi ABC selezionati nella pagina specificata tramite l'API.
         * Ogni blocco viene "wrappato" aggiungendo, prima e dopo, una riga di commento (con "%")
         * e dei newline, garantendo la separazione necessaria per abcjs.
         */
        function copyBlocksToTuneBook(blocks, tuneBookTitle) {
            var api = new mw.Api();
            // Per ciascun blocco, aggiunge newline e una riga di commento prima e dopo
            var wrappedBlocks = blocks.map(function(block) {
                return "\n\n%\n" + block + "\n%\n\n";
            });
            var textToAppend = wrappedBlocks.join("");
            console.log("Appending the following text to", tuneBookTitle, ":", textToAppend);
            api.postWithToken('csrf', {
                action: 'edit',
                title: tuneBookTitle,
                appendtext: textToAppend,
                summary: 'Copied selected ABC blocks via TuneBook selection dialog'
            }).done(function (result) {
                console.log("API post result:", result); // Mostra l'oggetto result completo
                if (result.edit && result.edit.captcha) {
                    console.log("Captcha challenge detected:", result.edit.captcha);
                }
if (result.edit && result.edit.result === 'Success') {
    var domain = window.location.origin;  // Oppure imposta manualmente, ad es. "https://mioDominio.org"
    var urlTitle = tuneBookTitle.replace(/\s+/g, '_');
    var tuneBookUrl = domain + '/wiki/' + urlTitle;
    
    // Creiamo un messaggio che include un vero link cliccabile
    var messageHtml = new OO.ui.HtmlSnippet(
        'Tunes successfully added to your own <br><br><center><a href="' + tuneBookUrl + '" target="_blank">TuneBook</a></center> <br>You can find it in My Pages under your Personal Menu or simply click the link above (<em>which will open a new tab</em>).'
    );
    
    // Mostriamo un dialogo di tipo OO.ui.MessageDialog con il testo HTML
    var windowManager = new OO.ui.WindowManager();
    $(document.body).append(windowManager.$element);
    var messageDialog = new OO.ui.MessageDialog();
    windowManager.addWindows([ messageDialog ]);
    windowManager.openWindow(messageDialog, {
        title: 'Success',
        message: messageHtml
    });
} else {
    console.log("Unexpected API result:", result);
    alert('Error copying Tunes to ' + tuneBookTitle);
}
            }).fail(function (err) {
                console.error("Error during API post:", err);
                alert('API error.');
            });
        }

        /********************************************************************
         * 2) Toolbox Integration: Add link to open the dialog
         ********************************************************************/
        function openTuneBookSelectionDialog() {
            var windowManager = new OO.ui.WindowManager();
            $(document.body).append(windowManager.$element);
            var dialog = new TuneBookSelectionDialog();
            windowManager.addWindows([dialog]);
            windowManager.openWindow(dialog);
        }

 function addTuneBookSelectionLink() {
    var $actions = $('#p-cactions ul');
    if ($actions.length === 0) { return; }
    if ($('#tunebook-selection').length === 0) {
        var $newLink = $('<li><a href="#" id="tunebook-selection">📋 Create a TuneBook</a></li>');
        $actions.append($newLink);
        console.log("TuneBook selection link added to Actions.");
    }
}

        $(document).on('click', '#tunebook-selection', function (e) {
            e.preventDefault();
            openTuneBookSelectionDialog();
        });

        // Inizializza
        $(addTuneBookSelectionLink);
    });
})(jQuery, mediaWiki, OO);
Cookies help us deliver our services. By using The Traditional Tune Archive services, you agree to our use of cookies.