Jump to content
Basculer le menu
Changer de menu des préférences
Basculer le menu personnel
Non connecté(e)
Votre adresse IP sera visible au public si vous faites des modifications.

« MediaWiki:Common.js » : différence entre les versions

Page de l’interface de MediaWiki
Gadget téléchargements v3 — boîtes de clés + URL auto-corrigée (Infothèque)
Contenu remplacé par « Tout JavaScript présent ici sera exécuté par tous les utilisateurs à chaque chargement de page. : ============================================================ * Barre de recherche de la page d'accueil * ============================================================ : (function () { 'use strict'; function init() { var trigger = document.querySelector('.ith-home-search'); var real = document.getElementById('citizen-search-summa... »
Balise : Contenu remplacé
 
(4 versions intermédiaires par le même utilisateur non affichées)
Ligne 2 : Ligne 2 :


/* ============================================================
/* ============================================================
  * Infothèque — Gadget "Ajouter un téléchargement"
  * Barre de recherche de la page d'accueil
* À coller dans : MediaWiki:Common.js (à la suite du contenu existant)
*
* N'agit que sur la page d'édition en mode source (là où
* #wpTextbox1 existe). Ajoute un bouton qui ouvre un petit
* formulaire, puis insère automatiquement le bon bloc de
* paramètres numérotés dans l'appel {{Téléchargements|...}}
* existant (ou en crée un nouveau à l'endroit du curseur si
* aucun n'est trouvé sur la page).
*
* - Le format (disquette / CD / ZIP) est traduit automatiquement
*  en icône — voir ITH_DL_FORMATS ci-dessous.
* - Plusieurs images possibles : 1 image = insérée telle quelle,
*  2+ images = galerie en grille (<gallery mode="packed">).
* - Un champ "Clé de produit / n° de série" facultatif, ajouté
*  proprement à la description (formaté en <code>).
* - Toute valeur libre insérée dans le wikitexte a ses "|"
*  échappés en {{!}}, sinon un pipe tapé par l'utilisateur
*  casserait l'appel du modèle (même souci que celui qui
*  cassait le rendu du tableau — voir Modèle:Téléchargements).
  * ============================================================ */
  * ============================================================ */
(function () {
(function () {
     'use strict';
     'use strict';
    var ITH_DL_FORMATS = {
        disquette: { label: 'Disquette', wikitext: '[[Fichier:Icône disquettes.png|centré]]' },
        cd: { label: 'CD-ROM / DVD', wikitext: '[[Fichier:Icone_CD.png|centré|sans_cadre]]' },
        zip: { label: 'Fichier ZIP / téléchargement numérique', wikitext: '[[Fichier:Zipfldr.dll 14 123-3.png|centré|sans_cadre]]' },
        autre: { label: 'Autre (icône personnalisée)', wikitext: '' }
    };
    function escapePipes(str) {
        return String(str || '').split('|').join('{{!}}');
    }


     function init() {
     function init() {
         var textarea = document.getElementById('wpTextbox1');
         var trigger = document.querySelector('.ith-home-search');
         if (!textarea) {
        var real = document.getElementById('citizen-search-summary');
             return; // pas en édition source
         if (!trigger || !real) {
             return;
         }
         }
         addButton(textarea);
         trigger.setAttribute('role', 'button');
    }
         trigger.setAttribute('tabindex', '0');
 
         trigger.addEventListener('click', function () {
    function addButton(textarea) {
             real.click();
        var btn = document.createElement('button');
        btn.type = 'button';
         btn.id = 'ith-dl-add-btn';
        btn.className = 'ith-dl-add-btn';
        btn.textContent = '+ Ajouter un téléchargement';
        btn.addEventListener('click', function () {
            openModal(textarea);
        });
        textarea.parentNode.insertBefore(btn, textarea);
    }
 
    function openModal(textarea) {
        var overlay = document.createElement('div');
         overlay.className = 'ith-dl-overlay';
 
        var box = document.createElement('div');
        box.className = 'ith-dl-modal';
        box.innerHTML =
            '<h3>Ajouter un téléchargement</h3>' +
            '<label>Édition <span class="ith-dl-req">*</span><input type="text" id="ith-dl-edition" placeholder="Ex : Windows 95"></label>' +
            '<label>Version<input type="text" id="ith-dl-version" placeholder="Ex : OSR 2.5 OEM 4.03.1216"></label>' +
            '<label>Langue<input type="text" id="ith-dl-langue" value="Français"></label>' +
            '<label>Description<textarea id="ith-dl-description" rows="2" placeholder="Notes libres, facultatif"></textarea></label>' +
            '<label>Clé de produit / n° de série<textarea id="ith-dl-serial" rows="2" placeholder="Facultatif. Une ligne par clé, ex :&#10;Product key: XXXXX-XXXXX-XXXXX&#10;Code key: 341-0005934"></textarea></label>' +
            '<label>Format<select id="ith-dl-format"></select></label>' +
            '<label id="ith-dl-format-autre-wrap" style="display:none">Icône personnalisée (wikitexte)<input type="text" id="ith-dl-format-autre" placeholder="[[Fichier:Mon icône.png|centré]]"></label>' +
            '<label>Images (photos, boîtes, disques...)</label>' +
            '<div id="ith-dl-images"></div>' +
            '<button type="button" id="ith-dl-add-image" class="ith-dl-btn-secondary ith-dl-btn-small">+ Ajouter une image</button>' +
            '<label style="margin-top:12px">Liens de téléchargement <span class="ith-dl-req">*</span>' +
            '<textarea id="ith-dl-liens" rows="3" placeholder="Une ligne par lien, format : URL | Texte du lien"></textarea>' +
            '</label>' +
            '<div class="ith-dl-actions">' +
            '<button type="button" id="ith-dl-cancel" class="ith-dl-btn-secondary">Annuler</button>' +
            '<button type="button" id="ith-dl-submit" class="ith-dl-btn-primary">Ajouter</button>' +
            '</div>' +
            '<p class="ith-dl-error" id="ith-dl-error" style="display:none"></p>';
 
        overlay.appendChild(box);
        document.body.appendChild(overlay);
 
        var select = box.querySelector('#ith-dl-format');
        Object.keys(ITH_DL_FORMATS).forEach(function (key) {
             var opt = document.createElement('option');
            opt.value = key;
            opt.textContent = ITH_DL_FORMATS[key].label;
            select.appendChild(opt);
         });
         });
         select.addEventListener('change', function () {
         trigger.addEventListener('keydown', function (e) {
            var autreWrap = box.querySelector('#ith-dl-format-autre-wrap');
             if (e.key === 'Enter' || e.key === ' ') {
            autreWrap.style.display = select.value === 'autre' ? '' : 'none';
                 e.preventDefault();
        });
                 real.click();
 
        var imagesWrap = box.querySelector('#ith-dl-images');
        function addImageRow() {
            var row = document.createElement('div');
            row.className = 'ith-dl-image-row';
            row.innerHTML =
                '<input type="text" class="ith-dl-image-file" placeholder="Nom du fichier, ex : Win95disks.jpg">' +
                '<input type="text" class="ith-dl-image-caption" placeholder="Légende (facultatif)">' +
                '<button type="button" class="ith-dl-btn-remove-image" title="Retirer">×</button>';
            row.querySelector('.ith-dl-btn-remove-image').addEventListener('click', function () {
                imagesWrap.removeChild(row);
            });
            imagesWrap.appendChild(row);
        }
        addImageRow(); // une première ligne par défaut
        box.querySelector('#ith-dl-add-image').addEventListener('click', addImageRow);
 
        box.querySelector('#ith-dl-cancel').addEventListener('click', closeModal);
        overlay.addEventListener('click', function (e) {
             if (e.target === overlay) closeModal();
        });
 
        box.querySelector('#ith-dl-submit').addEventListener('click', function () {
            submit(textarea);
        });
 
        function closeModal() {
            document.body.removeChild(overlay);
        }
 
        function buildImageWikitext() {
            var rows = Array.prototype.slice.call(imagesWrap.querySelectorAll('.ith-dl-image-row'));
            var images = rows.map(function (row) {
                var file = row.querySelector('.ith-dl-image-file').value.trim();
                var caption = row.querySelector('.ith-dl-image-caption').value.trim();
                return { file: file, caption: caption };
            }).filter(function (img) { return img.file; });
 
            if (images.length === 0) {
                return '';
            }
            if (images.length === 1) {
                var f = images[0].file.replace(/^Fichier:/i, '');
                var parts = ['[[Fichier:' + f, 'centré', 'vignette'];
                if (images[0].caption) parts.push(images[0].caption);
                return parts.join('|') + ']]';
            }
            var lines = images.map(function (img) {
                var f = img.file.replace(/^Fichier:/i, '');
                return 'Fichier:' + f + (img.caption ? '|' + img.caption : '');
            });
            return '<gallery mode="packed">\n' + lines.join('\n') + '\n</gallery>';
        }
 
        function buildDescriptionWithSerial(description, serialRaw) {
            var serialLines = serialRaw.split('\n').map(function (l) { return l.trim(); }).filter(Boolean);
            if (serialLines.length === 0) {
                return description;
            }
            // Une boîte grise par ligne, comme sur l'ancien wiki (une par clé/numéro).
            var serialBlock = serialLines.map(function (l) {
                return '<div class="ith-dl-serialbox">' + l + '</div>';
            }).join('');
            return description ? description + '\n' + serialBlock : serialBlock;
        }
 
        function submit(ta) {
            var edition = box.querySelector('#ith-dl-edition').value.trim();
            var liensRaw = box.querySelector('#ith-dl-liens').value.trim();
            var errEl = box.querySelector('#ith-dl-error');
 
            if (!edition || !liensRaw) {
                 errEl.textContent = 'Édition et au moins un lien de téléchargement sont obligatoires.';
                errEl.style.display = '';
                return;
            }
 
            var version = box.querySelector('#ith-dl-version').value.trim();
            var langue = box.querySelector('#ith-dl-langue').value.trim();
            var descriptionRaw = box.querySelector('#ith-dl-description').value.trim();
            var serialRaw = box.querySelector('#ith-dl-serial').value.trim();
            var description = buildDescriptionWithSerial(descriptionRaw, serialRaw);
            var formatKey = select.value;
            var format = formatKey === 'autre'
                 ? box.querySelector('#ith-dl-format-autre').value.trim()
                : ITH_DL_FORMATS[formatKey].wikitext;
            var image = buildImageWikitext();
            var liens = buildLiens(liensRaw);
 
            var data = {
                edition: edition,
                version: version,
                langue: langue,
                description: description,
                format: format,
                image: image,
                liens: liens
            };
 
            insertIntoTextarea(ta, data);
            closeModal();
        }
    }
 
    function buildLiens(raw) {
        var lines = raw.split('\n').map(function (l) { return l.trim(); }).filter(Boolean);
        var formatted = lines.map(function (line) {
            var parts = line.split('|');
            var url = (parts[0] || '').trim();
            var texte = (parts[1] || 'Téléchargement').trim();
            // MediaWiki n'affiche un lien externe que si l'URL a un schéma
            // (http://, https://, ftp://...) — sans ça, le [url texte]
            // s'affiche tel quel comme du texte brut avec les crochets.
            if (url && !/^[a-z][a-z0-9+.-]*:\/\//i.test(url)) {
                url = 'https://' + url;
             }
             }
            return '[' + url + ' ' + texte + ']';
         });
         });
        if (formatted.length === 1) {
            return formatted[0];
        }
        return formatted.map(function (f) { return '* ' + f; }).join('\n');
    }
    function insertIntoTextarea(textarea, data) {
        var text = textarea.value;
        var startIdx = text.indexOf('{{Téléchargements');
        if (startIdx === -1) {
            var block = '{{Téléchargements\n' + buildParamLines(1, data) + '\n}}';
            insertAtCursor(textarea, block);
            return;
        }
        // Trouve l'accolade fermante correspondante en comptant la profondeur des {{ }}.
        var depth = 0;
        var endIdx = -1;
        for (var i = startIdx; i < text.length - 1; i++) {
            if (text[i] === '{' && text[i + 1] === '{') { depth++; i++; }
            else if (text[i] === '}' && text[i + 1] === '}') {
                depth--; i++;
                if (depth === 0) { endIdx = i; break; }
            }
        }
        if (endIdx === -1) {
            // Structure inattendue : on n'insère pas au hasard, on ajoute un nouveau bloc à part.
            var fallback = '{{Téléchargements\n' + buildParamLines(1, data) + '\n}}';
            insertAtCursor(textarea, fallback);
            return;
        }
        var callText = text.slice(startIdx, endIdx + 1);
        var maxIndex = 0;
        var re = /edition(\d+)\s*=/g;
        var m;
        while ((m = re.exec(callText))) {
            maxIndex = Math.max(maxIndex, parseInt(m[1], 10));
        }
        var nextIndex = maxIndex + 1;
        if (nextIndex > 10) {
            alert('Ce tableau contient déjà 10 téléchargements (le maximum géré par le modèle). Préviens l\'admin du wiki pour étendre le modèle.');
            return;
        }
        var paramLines = buildParamLines(nextIndex, data);
        // insère juste avant le "}}" final (donc avant l'avant-dernier caractère de endIdx)
        var insertPos = endIdx - 1;
        var newText = text.slice(0, insertPos) + '\n' + paramLines + text.slice(insertPos);
        textarea.value = newText;
        textarea.dispatchEvent(new Event('input', { bubbles: true }));
        textarea.focus();
    }
    function buildParamLines(n, data) {
        // edition/version/langue/description = texte libre -> pipes échappés.
        // format/image/liens = wikitexte déjà construit ([[...]], <gallery>, [url texte])
        // dont les pipes internes sont protégés par [[ ]] / <gallery> / pas de pipe du tout.
        return [
            ' |edition' + n + '=' + escapePipes(data.edition),
            ' |version' + n + '=' + escapePipes(data.version),
            ' |langue' + n + '=' + escapePipes(data.langue),
            ' |description' + n + '=' + escapePipes(data.description),
            ' |format' + n + '=' + data.format,
            ' |image' + n + '=' + data.image,
            ' |liens' + n + '=' + data.liens
        ].join('\n');
    }
    function insertAtCursor(textarea, text) {
        var start = textarea.selectionStart || 0;
        var end = textarea.selectionEnd || 0;
        var before = textarea.value.slice(0, start);
        var after = textarea.value.slice(end);
        textarea.value = before + text + after;
        textarea.dispatchEvent(new Event('input', { bubbles: true }));
        textarea.focus();
     }
     }



Dernière version du 14 août 2026 à 16:00

/* Tout JavaScript présent ici sera exécuté par tous les utilisateurs à chaque chargement de page. */

/* ============================================================
 * Barre de recherche de la page d'accueil
 * ============================================================ */
(function () {
    'use strict';

    function init() {
        var trigger = document.querySelector('.ith-home-search');
        var real = document.getElementById('citizen-search-summary');
        if (!trigger || !real) {
            return;
        }
        trigger.setAttribute('role', 'button');
        trigger.setAttribute('tabindex', '0');
        trigger.addEventListener('click', function () {
            real.click();
        });
        trigger.addEventListener('keydown', function (e) {
            if (e.key === 'Enter' || e.key === ' ') {
                e.preventDefault();
                real.click();
            }
        });
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();