MediaWiki:Common.js: Difference between revisions
MediaWiki interface page
More actions
Palindromayd (talk | contribs) No edit summary |
Palindromayd (talk | contribs) No edit summary |
||
| Line 19: | Line 19: | ||
cmlimit: 500, | cmlimit: 500, | ||
cmsort: 'sortkey', | cmsort: 'sortkey', | ||
formatversion: 2, | |||
format: 'json' | format: 'json' | ||
} ); | } ); | ||
| Line 43: | Line 44: | ||
} | } | ||
/* ---------- Instant-create forms | /* ---------- Instant-create core (used by typed-name forms AND letter clicks) ---------- */ | ||
function fallbackToManualEditor( newTitle, preloadTitle, $status ) { | function fallbackToManualEditor( newTitle, preloadTitle, $status, reason ) { | ||
console.error( 'GAR instant-create fell back to manual editor. Reason: ' + reason + '. Title: ' + newTitle ); | |||
$status.text( ' Opening the normal editor instead...' ); | $status.text( ' Opening the normal editor instead...' ); | ||
window.location.href = mw.util.getUrl( newTitle, { action: 'edit', preload: preloadTitle } ); | window.location.href = mw.util.getUrl( newTitle, { action: 'edit', preload: preloadTitle } ); | ||
| Line 51: | Line 53: | ||
function safeReplacement( str ) { | function safeReplacement( str ) { | ||
return str.replace( /\$/g, '$$$$' ); | return str.replace( /\$/g, '$$$$' ); | ||
} | } | ||
| Line 85: | Line 85: | ||
action: 'query', | action: 'query', | ||
titles: newTitle, | titles: newTitle, | ||
formatversion: 2, | |||
format: 'json' | format: 'json' | ||
} ).then( function ( data ) { | } ).then( function ( data ) { | ||
var pages = data.query.pages; | var pages = ( data.query && data.query.pages ) || []; | ||
var exists = false; | var exists = false; | ||
pages.forEach( function ( page ) { | |||
if ( ! | if ( !page.missing ) { | ||
exists = true; | exists = true; | ||
} | } | ||
} | } ); | ||
if ( exists ) { | if ( exists ) { | ||
| Line 107: | Line 108: | ||
rvprop: 'content', | rvprop: 'content', | ||
rvslots: 'main', | rvslots: 'main', | ||
formatversion: 2, | |||
format: 'json' | format: 'json' | ||
} ).then( function ( tplData ) { | } ).then( function ( tplData ) { | ||
var tplPages = tplData.query.pages; | var tplPages = ( tplData.query && tplData.query.pages ) || []; | ||
var rawText = ''; | var rawText = ''; | ||
tplPages.forEach( function ( page ) { | |||
if ( page.revisions && page.revisions[ 0 ] && page.revisions[ 0 ].slots && page.revisions[ 0 ].slots.main ) { | |||
rawText = page.revisions[ 0 ].slots.main.content; | |||
rawText = | |||
} | } | ||
} ); | |||
if ( !rawText ) { | |||
fallbackToManualEditor( newTitle, preloadTitle, $status, 'preload template came back empty' ); | |||
return; | |||
} | } | ||
| Line 125: | Line 131: | ||
text: finalText, | text: finalText, | ||
createonly: true, | createonly: true, | ||
formatversion: 2, | |||
summary: 'Auto-created' | summary: 'Auto-created' | ||
} ).then( function ( editResult ) { | } ).then( function ( editResult ) { | ||
| Line 130: | Line 137: | ||
window.location.href = mw.util.getUrl( newTitle ); | window.location.href = mw.util.getUrl( newTitle ); | ||
} else { | } else { | ||
fallbackToManualEditor( newTitle, preloadTitle, $status ); | fallbackToManualEditor( newTitle, preloadTitle, $status, 'edit call did not report Success' ); | ||
} | } | ||
}, function () { | }, function ( code, err ) { | ||
fallbackToManualEditor( newTitle, preloadTitle, $status ); | fallbackToManualEditor( newTitle, preloadTitle, $status, 'edit call failed: ' + code ); | ||
} ); | } ); | ||
}, function () { | }, function ( code, err ) { | ||
fallbackToManualEditor( newTitle, preloadTitle, $status ); | fallbackToManualEditor( newTitle, preloadTitle, $status, 'template fetch failed: ' + code ); | ||
} ); | } ); | ||
}, function () { | }, function ( code, err ) { | ||
fallbackToManualEditor( newTitle, preloadTitle, $status ); | fallbackToManualEditor( newTitle, preloadTitle, $status, 'existence check failed: ' + code ); | ||
} ); | } ); | ||
} ); | } ); | ||
} | } | ||
/* ---------- Typed-name forms (Platform, Country, City, Person, Case) ---------- */ | |||
function buildForm( $container ) { | function buildForm( $container ) { | ||
| Line 155: | Line 164: | ||
var extraInputs = {}; | var extraInputs = {}; | ||
var plainExtraInputs = []; | |||
if ( extraFieldsRaw ) { | if ( extraFieldsRaw ) { | ||
extraFieldsRaw.split( ';' ).forEach( function ( pair ) { | extraFieldsRaw.split( ';' ).forEach( function ( pair ) { | ||
| Line 165: | Line 176: | ||
} else { | } else { | ||
$extra = $( '<input>' ).attr( 'type', 'text' ).attr( 'placeholder', label ).css( 'width', '100%' ).css( 'margin-bottom', '6px' ); | $extra = $( '<input>' ).attr( 'type', 'text' ).attr( 'placeholder', label ).css( 'width', '100%' ).css( 'margin-bottom', '6px' ); | ||
plainExtraInputs.push( $extra ); | |||
} | } | ||
extraInputs[ key ] = $extra; | extraInputs[ key ] = $extra; | ||
| Line 177: | Line 189: | ||
$container.empty().append( $wrapper ); | $container.empty().append( $wrapper ); | ||
function submit() { | |||
var name = $.trim( $input.val() ); | var name = $.trim( $input.val() ); | ||
if ( !name ) { | if ( !name ) { | ||
| Line 187: | Line 199: | ||
} | } | ||
runInstantCreate( prefix + name, preloadTitle, fields, $status ); | runInstantCreate( prefix + name, preloadTitle, fields, $status ); | ||
} | |||
$button.on( 'click', submit ); | |||
// Enter submits from the name field or any plain (non-textarea) extra field. | |||
$input.on( 'keydown', function ( e ) { | |||
if ( e.which === 13 ) { | |||
e.preventDefault(); | |||
submit(); | |||
} | |||
} ); | |||
plainExtraInputs.forEach( function ( $extra ) { | |||
$extra.on( 'keydown', function ( e ) { | |||
if ( e.which === 13 ) { | |||
e.preventDefault(); | |||
submit(); | |||
} | |||
} ); | |||
} ); | |||
} | |||
/* ---------- Letter-grid clicks (A-Z navigation hops) ---------- */ | |||
function bindInstantLetter( $el ) { | |||
$el.on( 'click', function () { | |||
var title = $el.data( 'title' ); | |||
var preload = $el.data( 'preload' ); | |||
var $status = $( '<span>' ).addClass( 'gar-instant-status' ); | |||
$el.after( $status ); | |||
$el.off( 'click' ); | |||
$el.css( 'cursor', 'default' ); | |||
runInstantCreate( title, preload, {}, $status ); | |||
} ); | } ); | ||
} | } | ||
| Line 198: | Line 242: | ||
$content.find( '.gar-instant-create' ).each( function () { | $content.find( '.gar-instant-create' ).each( function () { | ||
buildForm( $( this ) ); | buildForm( $( this ) ); | ||
} ); | |||
$content.find( '.gar-instant-letter' ).each( function () { | |||
bindInstantLetter( $( this ) ); | |||
} ); | } ); | ||
} ); | } ); | ||
}() ); | }() ); | ||
Revision as of 18:42, 27 June 2026
( function () {
'use strict';
/* ---------- Live auto-updating grid (Platforms, Countries, Cities, etc.) ---------- */
function renderAutoGrid( $container ) {
var category = $container.data( 'category' );
if ( !category ) {
return;
}
$container.text( 'Loading...' );
mw.loader.using( 'mediawiki.api' ).then( function () {
return new mw.Api().get( {
action: 'query',
list: 'categorymembers',
cmtitle: 'Category:' + category,
cmlimit: 500,
cmsort: 'sortkey',
formatversion: 2,
format: 'json'
} );
} ).then( function ( data ) {
var members = ( data.query && data.query.categorymembers ) || [];
$container.empty();
if ( members.length === 0 ) {
$container.append( $( '<p>' ).text( 'Nothing has been added here yet.' ) );
return;
}
members.forEach( function ( member ) {
var title = member.title;
var displayName = title.split( ':' ).slice( 1 ).join( ':' ).split( '/' ).pop();
var $link = $( '<a>' )
.attr( 'href', mw.util.getUrl( title ) )
.text( displayName );
$container.append( $link );
} );
}, function () {
$container.text( 'Could not load this list right now.' );
} );
}
/* ---------- Instant-create core (used by typed-name forms AND letter clicks) ---------- */
function fallbackToManualEditor( newTitle, preloadTitle, $status, reason ) {
console.error( 'GAR instant-create fell back to manual editor. Reason: ' + reason + '. Title: ' + newTitle );
$status.text( ' Opening the normal editor instead...' );
window.location.href = mw.util.getUrl( newTitle, { action: 'edit', preload: preloadTitle } );
}
function safeReplacement( str ) {
return str.replace( /\$/g, '$$$$' );
}
function applyExtraFields( rawText, fields ) {
var text = rawText;
if ( fields.image ) {
text = text.replace( /\|image(\s*)=\s*\n/, function ( match, spacing ) {
return '|image' + spacing + '= ' + safeReplacement( fields.image ) + '\n';
} );
}
if ( fields.evidence ) {
text = text.replace( '<Add Picture Here>', safeReplacement( fields.evidence ) );
}
if ( fields.description ) {
text = text.replace( '<Write Text Here>', safeReplacement( fields.description ) );
}
return text;
}
function runInstantCreate( newTitle, preloadTitle, fields, $status ) {
$status.text( ' Creating...' );
mw.loader.using( 'mediawiki.api' ).then( function () {
var api = new mw.Api();
api.get( {
action: 'query',
titles: newTitle,
formatversion: 2,
format: 'json'
} ).then( function ( data ) {
var pages = ( data.query && data.query.pages ) || [];
var exists = false;
pages.forEach( function ( page ) {
if ( !page.missing ) {
exists = true;
}
} );
if ( exists ) {
$status.text( ' Already exists, opening it...' );
window.location.href = mw.util.getUrl( newTitle );
return;
}
api.get( {
action: 'query',
titles: preloadTitle,
prop: 'revisions',
rvprop: 'content',
rvslots: 'main',
formatversion: 2,
format: 'json'
} ).then( function ( tplData ) {
var tplPages = ( tplData.query && tplData.query.pages ) || [];
var rawText = '';
tplPages.forEach( function ( page ) {
if ( page.revisions && page.revisions[ 0 ] && page.revisions[ 0 ].slots && page.revisions[ 0 ].slots.main ) {
rawText = page.revisions[ 0 ].slots.main.content;
}
} );
if ( !rawText ) {
fallbackToManualEditor( newTitle, preloadTitle, $status, 'preload template came back empty' );
return;
}
var finalText = applyExtraFields( rawText, fields );
api.postWithToken( 'csrf', {
action: 'edit',
title: newTitle,
text: finalText,
createonly: true,
formatversion: 2,
summary: 'Auto-created'
} ).then( function ( editResult ) {
if ( editResult && editResult.edit && editResult.edit.result === 'Success' ) {
window.location.href = mw.util.getUrl( newTitle );
} else {
fallbackToManualEditor( newTitle, preloadTitle, $status, 'edit call did not report Success' );
}
}, function ( code, err ) {
fallbackToManualEditor( newTitle, preloadTitle, $status, 'edit call failed: ' + code );
} );
}, function ( code, err ) {
fallbackToManualEditor( newTitle, preloadTitle, $status, 'template fetch failed: ' + code );
} );
}, function ( code, err ) {
fallbackToManualEditor( newTitle, preloadTitle, $status, 'existence check failed: ' + code );
} );
} );
}
/* ---------- Typed-name forms (Platform, Country, City, Person, Case) ---------- */
function buildForm( $container ) {
var prefix = $container.data( 'prefix' );
var preloadTitle = $container.data( 'preload' );
var placeholder = $container.data( 'placeholder' ) || 'Enter a name';
var buttonLabel = $container.data( 'buttonlabel' ) || 'Add';
var extraFieldsRaw = $container.data( 'extrafields' ) || '';
var $input = $( '<input>' ).attr( 'type', 'text' ).attr( 'placeholder', placeholder ).css( 'width', '100%' ).css( 'margin-bottom', '6px' );
var $wrapper = $( '<div>' ).append( $input );
var extraInputs = {};
var plainExtraInputs = [];
if ( extraFieldsRaw ) {
extraFieldsRaw.split( ';' ).forEach( function ( pair ) {
var parts = pair.split( ':' );
var key = $.trim( parts[ 0 ] );
var label = $.trim( parts[ 1 ] || key );
var $extra;
if ( key === 'description' ) {
$extra = $( '<textarea>' ).attr( 'placeholder', label ).attr( 'rows', 3 ).css( 'width', '100%' ).css( 'margin-bottom', '6px' );
} else {
$extra = $( '<input>' ).attr( 'type', 'text' ).attr( 'placeholder', label ).css( 'width', '100%' ).css( 'margin-bottom', '6px' );
plainExtraInputs.push( $extra );
}
extraInputs[ key ] = $extra;
$wrapper.append( $( '<div>' ).append( $extra ) );
} );
}
var $button = $( '<button>' ).text( buttonLabel );
var $status = $( '<span>' ).addClass( 'gar-instant-status' );
$wrapper.append( $button, ' ', $status );
$container.empty().append( $wrapper );
function submit() {
var name = $.trim( $input.val() );
if ( !name ) {
return;
}
var fields = {};
for ( var key in extraInputs ) {
fields[ key ] = $.trim( extraInputs[ key ].val() );
}
runInstantCreate( prefix + name, preloadTitle, fields, $status );
}
$button.on( 'click', submit );
// Enter submits from the name field or any plain (non-textarea) extra field.
$input.on( 'keydown', function ( e ) {
if ( e.which === 13 ) {
e.preventDefault();
submit();
}
} );
plainExtraInputs.forEach( function ( $extra ) {
$extra.on( 'keydown', function ( e ) {
if ( e.which === 13 ) {
e.preventDefault();
submit();
}
} );
} );
}
/* ---------- Letter-grid clicks (A-Z navigation hops) ---------- */
function bindInstantLetter( $el ) {
$el.on( 'click', function () {
var title = $el.data( 'title' );
var preload = $el.data( 'preload' );
var $status = $( '<span>' ).addClass( 'gar-instant-status' );
$el.after( $status );
$el.off( 'click' );
$el.css( 'cursor', 'default' );
runInstantCreate( title, preload, {}, $status );
} );
}
/* ---------- Wire everything up once the page content is ready ---------- */
mw.hook( 'wikipage.content' ).add( function ( $content ) {
$content.find( '.gar-auto-grid' ).each( function () {
renderAutoGrid( $( this ) );
} );
$content.find( '.gar-instant-create' ).each( function () {
buildForm( $( this ) );
} );
$content.find( '.gar-instant-letter' ).each( function () {
bindInstantLetter( $( this ) );
} );
} );
}() );