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.
Version datée du 12 août 2026 à 11:12 par Admin (discussion | contributions) (Gadget téléchargements v4 — 6 formats d'icônes (Infothèque))

Note : après avoir publié vos modifications, il se peut que vous deviez forcer le rechargement complet du cache de votre navigateur pour voir les changements.

  • Firefox / Safari : maintenez la touche Maj (Shift) en cliquant sur le bouton Actualiser ou appuyez sur Ctrl + F5 ou Ctrl + R (⌘ + R sur un Mac).
  • Google Chrome : appuyez sur Ctrl + Maj + R (⌘ + Shift + R sur un Mac).
  •  Edge : maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl + F5.
/* Tout JavaScript présent ici sera exécuté par tous les utilisateurs à chaque chargement de page. */

/* ============================================================
 * Infothèque — Gadget "Ajouter un téléchargement"
 * À 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 () {
    'use strict';

    var ITH_DL_FORMATS = {
        disquette: { label: 'Disquette', wikitext: '[[Fichier:Icône disquettes.png|centré]]' },
        disquette2: { label: 'Disquette (variante)', wikitext: '[[Fichier:Setupapi.dll 14 105.png|centré|sans_cadre]]' },
        cd: { label: 'CD-ROM / DVD', wikitext: '[[Fichier:Icone CD.png|centré|sans_cadre]]' },
        cddisquette: { label: 'CD + disquettes', wikitext: '[[Fichier:Mmcndmgr.dll 14 30548-1.png|centré|sans_cadre]]' },
        zip: { label: 'Fichier ZIP / téléchargement numérique', wikitext: '[[Fichier:Zipfldr.dll 14 123-3.png|centré|sans_cadre]]' },
        installateur: { label: 'Installateur (.exe)', wikitext: '[[Fichier:Netsetup.exe 14 3000-0.png|centré|sans_cadre]]' },
        autre: { label: 'Autre (icône personnalisée)', wikitext: '' }
    };

    function escapePipes(str) {
        return String(str || '').split('|').join('{{!}}');
    }

    function init() {
        var textarea = document.getElementById('wpTextbox1');
        if (!textarea) {
            return; // pas en édition source
        }
        addButton(textarea);
    }

    function addButton(textarea) {
        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 () {
            var autreWrap = box.querySelector('#ith-dl-format-autre-wrap');
            autreWrap.style.display = select.value === 'autre' ? '' : 'none';
        });

        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();
    }

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