Note : après avoir enregistré la page, vous devrez forcer le rechargement complet du cache de votre navigateur pour voir les changements.

Mozilla / Firefox / Konqueror / Safari : maintenez la touche Majuscule (Shift) en cliquant sur le bouton Actualiser (Reload) ou pressez Maj-Ctrl-R (Cmd-R sur Apple Mac) ;

Firefox (sur GNU/Linux) / Chrome / Internet Explorer / Opera : maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl-F5.
/**
 * Gadget pour remplacer {{Classements mondiaux UCI}} par {{Cycling race/Riderranking|QXXXXXXXX}} via Wikidata
 *
 * @author Claude (Anthropic) - Conversation avec Guillaumrs
 * @date Mai 2026
 * @version 1.2
 */

( function () {
	'use strict';

	/* ── Seulement en espace principal et Wikipédia ── */
	var ns = mw.config.get( 'wgNamespaceNumber' );
	if ( ns !== 0 && ns !== 4 ) return;

	/* ── Seulement en mode lecture ── */
	if ( mw.config.get( 'wgAction' ) !== 'view' ) return;

	/* ── Regex : repère le bloc complet ──
	   IMPORTANT : ne pas utiliser le flag /g sur une regex réutilisée avec .test()
	   car lastIndex avance et provoque des faux négatifs en alternance.
	   On recrée la regex à chaque usage, ou on utilise une fonction. */
	function hasUciBlock( text ) {
		return /\{\{Classements mondiaux UCI\/En-tête\}\}[\s\S]*?\{\{Classements mondiaux UCI\/Fin\}\}/i.test( text );
	}

	function replaceUciBlock( text, replacement ) {
		return text.replace(
			/\{\{Classements mondiaux UCI\/En-tête\}\}[\s\S]*?\{\{Classements mondiaux UCI\/Fin\}\}/gi,
			replacement
		);
	}

	function getWikidataQid() {
		return mw.config.get( 'wgWikibaseItemId' ) || null;
	}

	/* ────────────────────────────────────────────────────────
	   Applique la modification via l'API MediaWiki
	──────────────────────────────────────────────────────── */
	function doReplace( qid ) {
		var api      = new mw.Api();
		var pageName = mw.config.get( 'wgPageName' );

		api.get( {
			action       : 'query',
			prop         : 'revisions',
			titles       : pageName,
			rvprop       : 'content',
			rvslots      : 'main',
			formatversion: 2
		} ).done( function ( data ) {
			var page    = data.query.pages[ 0 ];
			var oldText = page.revisions[ 0 ].slots.main.content;

			if ( !hasUciBlock( oldText ) ) {
				mw.notify( 'Aucun bloc {{Classements mondiaux UCI}} trouvé.', { type: 'warn' } );
				return;
			}

			var newTemplate = '{{Cycling race/Riderranking|' + qid + '}}';
			var newText     = replaceUciBlock( oldText, newTemplate );

			var summary =
				'Remplacement du modèle obsolète ' +
				'[[Modèle:Classements mondiaux UCI|{{Classements mondiaux UCI}}]] ' +
				'par [[Modèle:Cycling race/Riderranking|{{Cycling race/Riderranking}}]] ' +
				'avec intégration des données Wikidata (' + qid + ') ' +
				'([[Utilisateur:Guillaumrs/RiderRaking.js|script]])';

			api.postWithToken( 'csrf', {
				action   : 'edit',
				title    : pageName,
				text     : newText,
				summary  : summary,
				notminor : true,
				bot      : false
			} ).done( function ( result ) {
				if ( result.edit && result.edit.result === 'Success' ) {
					mw.notify( '✔ Modèle remplacé avec succès — rechargement…', { type: 'success' } );
					setTimeout( function () { location.reload(); }, 1200 );
				} else {
					mw.notify( 'Erreur lors de la sauvegarde.', { type: 'error' } );
					console.error( result );
				}
			} ).fail( function ( err ) {
				mw.notify( 'Erreur API : ' + err, { type: 'error' } );
				console.error( err );
			} );

		} ).fail( function ( err ) {
			mw.notify( 'Impossible de lire le wikicode.', { type: 'error' } );
			console.error( err );
		} );
	}

	/* ────────────────────────────────────────────────────────
	   Panneau flottant fixe
	──────────────────────────────────────────────────────── */
	function injectPanel( qid ) {
		/* Évite le double-ajout */
		if ( $( '#uci-replace-panel' ).length ) return;

		var $panel = $( '<div></div>' )
			.attr( 'id', 'uci-replace-panel' )
			.css( {
				'position'      : 'fixed',
				'bottom'        : '24px',
				'right'         : '24px',
				'z-index'       : '9998',  /* légèrement sous colonnes2 (9999) pour éviter la superposition */
				'background'    : '#1a1a2e',
				'border'        : '1px solid rgba(72,187,120,0.4)',
				'border-radius' : '12px',
				'padding'       : '12px 14px',
				'box-shadow'    : '0 4px 20px rgba(0,0,0,0.4)',
				'display'       : 'flex',
				'align-items'   : 'center',
				'gap'           : '10px',
				'font-family'   : 'sans-serif',
				'font-size'     : '13px',
				'color'         : '#e2e8f0',
				'max-width'     : '320px'
			} );

		/* Icône vélo */
		var $icon = $( '<span></span>' )
			.text( '🚴' )
			.css( { 'font-size': '20px', 'flex-shrink': '0' } );

		/* Texte */
		var $label = $( '<span></span>' )
			.html(
				'<strong style="color:#68d391;display:block;margin-bottom:2px">Classements mondiaux UCI</strong>' +
				'Modèle obsolète détecté — ' + mw.html.escape( qid )
			)
			.css( { 'line-height': '1.4', 'flex': '1' } );

		/* Bouton remplacer */
		var $btn = $( '<button></button>' )
			.text( '⇄ Remplacer' )
			.css( {
				'background'    : 'rgba(72,187,120,0.2)',
				'border'        : '1px solid rgba(72,187,120,0.5)',
				'color'         : '#68d391',
				'border-radius' : '8px',
				'padding'       : '5px 10px',
				'cursor'        : 'pointer',
				'font-size'     : '12px',
				'font-weight'   : 'bold',
				'white-space'   : 'nowrap',
				'transition'    : 'all 0.2s',
				'flex-shrink'   : '0'
			} )
			.on( 'mouseenter', function () {
				$( this ).css( {
					'background' : 'rgba(72,187,120,0.4)',
					'transform'  : 'scale(1.05)'
				} );
			} )
			.on( 'mouseleave', function () {
				$( this ).css( {
					'background' : 'rgba(72,187,120,0.2)',
					'transform'  : 'scale(1)'
				} );
			} )
			.on( 'click', function () {
				$( this ).text( '…' ).prop( 'disabled', true );
				doReplace( qid );
			} );

		/* Bouton fermer */
		var $close = $( '<button></button>' )
			.text( '×' )
			.attr( 'title', 'Fermer' )
			.css( {
				'background'    : 'none',
				'border'        : 'none',
				'color'         : '#718096',
				'font-size'     : '18px',
				'cursor'        : 'pointer',
				'padding'       : '0 2px',
				'line-height'   : '1',
				'flex-shrink'   : '0',
				'transition'    : 'color 0.2s'
			} )
			.on( 'mouseenter', function () { $( this ).css( 'color', '#fc8181' ); } )
			.on( 'mouseleave', function () { $( this ).css( 'color', '#718096' ); } )
			.on( 'click', function () { $panel.remove(); } );

		$panel.append( $icon, $label, $btn, $close );
		$( 'body' ).append( $panel );
	}

	/* ── Point d'entrée ──
	   On utilise uniquement 'mediawiki.api' qui est toujours disponible.
	   mw.notify fait partie du core MediaWiki et n'a pas besoin d'être chargé séparément. */
	$( function () {
		mw.loader.using( 'mediawiki.api', function () {
			var api = new mw.Api();
			api.get( {
				action       : 'query',
				prop         : 'revisions',
				titles       : mw.config.get( 'wgPageName' ),
				rvprop       : 'content',
				rvslots      : 'main',
				formatversion: 2
			} ).done( function ( data ) {
				var page = data.query.pages[ 0 ];
				if ( !page.revisions ) return;

				var src = page.revisions[ 0 ].slots.main.content;
				if ( !hasUciBlock( src ) ) return;

				var qid = getWikidataQid();
				if ( !qid ) {
					console.warn( '[RiderRaking] Pas de QID Wikidata pour cette page.' );
					return;
				}

				injectPanel( qid );
			} ).fail( function ( err ) {
				console.error( '[RiderRaking] Erreur lors de la lecture de la page :', err );
			} );
		} );
	} );

}() );