コンテンツにスキップ

「MediaWiki:Common.js」の版間の差分

提供: RTA Wiki
編集の要約なし
編集の要約なし
187行目: 187行目:
setUpRecordTimeInputs();
setUpRecordTimeInputs();
mw.hook( 'wikipage.content' ).add( setUpRecordTimeInputs );
mw.hook( 'wikipage.content' ).add( setUpRecordTimeInputs );
}
if ( document.readyState === 'loading' ) {
document.addEventListener( 'DOMContentLoaded', start );
} else {
start();
}
} );
/* RTA Wiki: 記録カードの並べ替え */
mw.loader.using( 'mediawiki.util' ).then( function () {
function setUpRecordCardSorts() {
document.querySelectorAll( '.rta-record-cards--sortable' ).forEach( function ( container, index ) {
if ( container.dataset.rtaSortable === '1' ) {
return;
}
container.dataset.rtaSortable = '1';
var control = document.createElement( 'div' );
var label = document.createElement( 'label' );
var select = document.createElement( 'select' );
var selectId = 'rta-record-sort-' + index;
control.className = 'rta-record-sort';
label.htmlFor = selectId;
label.textContent = '並び順:';
select.id = selectId;
[
[ 'time-asc', 'タイムが速い順' ],
[ 'time-desc', 'タイムが遅い順' ],
[ 'date-desc', '記録日が新しい順' ],
[ 'date-asc', '記録日が古い順' ]
].forEach( function ( item ) {
var option = document.createElement( 'option' );
option.value = item[ 0 ];
option.textContent = item[ 1 ];
select.appendChild( option );
} );
control.appendChild( label );
control.appendChild( select );
container.parentNode.insertBefore( control, container );
function sortCards() {
var cards = Array.from( container.children ).filter( function ( element ) {
return element.classList.contains( 'rta-record-card' );
} );
cards.sort( function ( a, b ) {
var mode = select.value;
var aSeconds = Number( a.dataset.rtaSeconds );
var bSeconds = Number( b.dataset.rtaSeconds );
var aDate = a.dataset.rtaDate || '';
var bDate = b.dataset.rtaDate || '';
if ( mode === 'time-asc' || mode === 'time-desc' ) {
if ( !Number.isFinite( aSeconds ) ) {
return 1;
}
if ( !Number.isFinite( bSeconds ) ) {
return -1;
}
return mode === 'time-asc' ?
aSeconds - bSeconds :
bSeconds - aSeconds;
}
if ( !aDate ) {
return 1;
}
if ( !bDate ) {
return -1;
}
return mode === 'date-asc' ?
aDate.localeCompare( bDate ) :
bDate.localeCompare( aDate );
} );
cards.forEach( function ( card ) {
container.appendChild( card );
} );
}
select.addEventListener( 'change', sortCards );
} );
}
function start() {
setUpRecordCardSorts();
mw.hook( 'wikipage.content' ).add( setUpRecordCardSorts );
}
}



2026年9月29日 (火) 21:57時点における版

/* RTA Wiki: 管理者以外には既存ページの編集導線を表示しない */
mw.loader.using( 'mediawiki.util' ).then( function () {
	function hideEditLinks() {
		if ( mw.config.get( 'wgUserGroups' ).includes( 'sysop' ) ) {
			return;
		}

		document.querySelectorAll(
			'#ca-edit, #ca-ve-edit, #ca-formedit, [id^="ca-formedit"], a[href*="action=formedit"]'
		).forEach( function ( element ) {
			( element.closest( 'li' ) || element ).remove();
		} );
	}

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

/* RTA Wiki: 時・分・秒の入力から記録時間・記録秒を自動設定する */
mw.loader.using( 'mediawiki.util' ).then( function () {
	function setUpRecordTimeInputs() {
		var timeInput = document.querySelector(
			'input[name="RTA記録[記録時間]"], input[name$="[記録時間]"]'
		);
		var secondsInput = document.querySelector(
			'input[name="RTA記録[記録秒]"], input[name$="[記録秒]"]'
		);
		var controls = document.getElementById( 'rta-time-inputs' );

		if (
			!timeInput || !secondsInput || !controls ||
			controls.dataset.rtaTimeSetUp === '1'
		) {
			return;
		}

		controls.dataset.rtaTimeSetUp = '1';
		controls.style.display = 'flex';
		controls.style.gap = '10px';
		controls.style.alignItems = 'center';
		controls.style.flexWrap = 'wrap';

		function makeInput( id, labelText, maxLength ) {
			var label = document.createElement( 'label' );
			var input = document.createElement( 'input' );

			label.appendChild( document.createTextNode( labelText + ' ' ) );

			input.id = id;
			input.type = 'text';
			input.inputMode = 'numeric';
			input.size = 3;
			input.maxLength = maxLength;
			input.value = '0';
input.autocomplete = 'off';
input.style.width = '4.5em';
input.style.boxSizing = 'border-box';

label.style.display = 'inline-flex';
label.style.alignItems = 'center';
label.style.gap = '4px';

label.appendChild( input );
			controls.appendChild( label );

			return input;
		}

		var hoursInput = makeInput( 'rta-record-hours', '時', 6 );
		var minutesInput = makeInput( 'rta-record-minutes', '分', 2 );
		var recordSecondsInput = makeInput( 'rta-record-seconds', '秒', 2 );

		var message = document.createElement( 'small' );
		message.style.display = 'block';
		message.style.marginTop = '4px';
		message.style.color = '#54595d';
		controls.insertAdjacentElement( 'afterend', message );

		function normalizeDigits( value ) {
			return value.replace( /[0-9]/g, function ( character ) {
				return String.fromCharCode( character.charCodeAt( 0 ) - 0xFEE0 );
			} ).trim();
		}

		function showMessage( text, isError ) {
			message.textContent = text;
			message.style.color = isError ? '#d33' : '#54595d';
		}

		function setVisibleValuesFromStoredTime() {
			var value = normalizeDigits( timeInput.value );
			var match = value.match( /^(\d+):([0-5]\d):([0-5]\d)$/ );

			if ( !match ) {
				return;
			}

			hoursInput.value = String( Number( match[1] ) );
			minutesInput.value = String( Number( match[2] ) );
			recordSecondsInput.value = String( Number( match[3] ) );
		}

		function updateRecordValues() {
			var hoursText = normalizeDigits( hoursInput.value );
			var minutesText = normalizeDigits( minutesInput.value );
			var secondsText = normalizeDigits( recordSecondsInput.value );

			hoursInput.value = hoursText;
			minutesInput.value = minutesText;
			recordSecondsInput.value = secondsText;

			if (
				!/^\d+$/.test( hoursText ) ||
				!/^\d+$/.test( minutesText ) ||
				!/^\d+$/.test( secondsText )
			) {
				timeInput.value = '';
				secondsInput.value = '';
				showMessage( '時・分・秒を数字で入力してください。', true );
				return false;
			}

			var hours = Number( hoursText );
			var minutes = Number( minutesText );
			var seconds = Number( secondsText );

			if (
				!Number.isSafeInteger( hours ) ||
				minutes > 59 ||
				seconds > 59
			) {
				timeInput.value = '';
				secondsInput.value = '';
				showMessage( '分・秒は 0〜59 の範囲で入力してください。', true );
				return false;
			}

			var totalSeconds = hours * 3600 + minutes * 60 + seconds;

			if ( totalSeconds === 0 ) {
				timeInput.value = '';
				secondsInput.value = '';
				showMessage( '0秒より大きい記録時間を入力してください。', true );
				return false;
			}

			timeInput.value =
				String( hours ) + ':' +
				String( minutes ).padStart( 2, '0' ) + ':' +
				String( seconds ).padStart( 2, '0' );
			secondsInput.value = String( totalSeconds );

			showMessage(
				'保存値: ' + timeInput.value + ' (' + secondsInput.value + ' 秒)',
				false
			);
			return true;
		}

		setVisibleValuesFromStoredTime();

		[ hoursInput, minutesInput, recordSecondsInput ].forEach( function ( input ) {
			input.addEventListener( 'input', updateRecordValues );
			input.addEventListener( 'change', updateRecordValues );
			input.addEventListener( 'blur', updateRecordValues );
		} );

		if ( timeInput.form ) {
			timeInput.form.addEventListener( 'submit', function ( event ) {
				if ( !updateRecordValues() ) {
					event.preventDefault();
				}
			} );
		}

		if ( timeInput.value ) {
	updateRecordValues();
} else {
	showMessage( '時・分・秒を入力してください。', false );
}
	}

	function start() {
		setUpRecordTimeInputs();
		mw.hook( 'wikipage.content' ).add( setUpRecordTimeInputs );
	}

	if ( document.readyState === 'loading' ) {
		document.addEventListener( 'DOMContentLoaded', start );
	} else {
		start();
	}
} );
/* RTA Wiki: 記録カードの並べ替え */
mw.loader.using( 'mediawiki.util' ).then( function () {
	function setUpRecordCardSorts() {
		document.querySelectorAll( '.rta-record-cards--sortable' ).forEach( function ( container, index ) {
			if ( container.dataset.rtaSortable === '1' ) {
				return;
			}
			container.dataset.rtaSortable = '1';

			var control = document.createElement( 'div' );
			var label = document.createElement( 'label' );
			var select = document.createElement( 'select' );
			var selectId = 'rta-record-sort-' + index;

			control.className = 'rta-record-sort';
			label.htmlFor = selectId;
			label.textContent = '並び順:';
			select.id = selectId;

			[
				[ 'time-asc', 'タイムが速い順' ],
				[ 'time-desc', 'タイムが遅い順' ],
				[ 'date-desc', '記録日が新しい順' ],
				[ 'date-asc', '記録日が古い順' ]
			].forEach( function ( item ) {
				var option = document.createElement( 'option' );
				option.value = item[ 0 ];
				option.textContent = item[ 1 ];
				select.appendChild( option );
			} );

			control.appendChild( label );
			control.appendChild( select );
			container.parentNode.insertBefore( control, container );

			function sortCards() {
				var cards = Array.from( container.children ).filter( function ( element ) {
					return element.classList.contains( 'rta-record-card' );
				} );

				cards.sort( function ( a, b ) {
					var mode = select.value;
					var aSeconds = Number( a.dataset.rtaSeconds );
					var bSeconds = Number( b.dataset.rtaSeconds );
					var aDate = a.dataset.rtaDate || '';
					var bDate = b.dataset.rtaDate || '';

					if ( mode === 'time-asc' || mode === 'time-desc' ) {
						if ( !Number.isFinite( aSeconds ) ) {
							return 1;
						}
						if ( !Number.isFinite( bSeconds ) ) {
							return -1;
						}
						return mode === 'time-asc' ?
							aSeconds - bSeconds :
							bSeconds - aSeconds;
					}

					if ( !aDate ) {
						return 1;
					}
					if ( !bDate ) {
						return -1;
					}

					return mode === 'date-asc' ?
						aDate.localeCompare( bDate ) :
						bDate.localeCompare( aDate );
				} );

				cards.forEach( function ( card ) {
					container.appendChild( card );
				} );
			}

			select.addEventListener( 'change', sortCards );
		} );
	}

	function start() {
		setUpRecordCardSorts();
		mw.hook( 'wikipage.content' ).add( setUpRecordCardSorts );
	}

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