MediaWiki:InitListingTools.js
Nota: Después de publicar, quizás necesite actualizar la caché de su navegador para ver los cambios.
- Firefox/Safari: Mantenga presionada la tecla Shift mientras pulsa el botón Actualizar, o presiona Ctrl+F5 o Ctrl+R (⌘+R en Mac)
- Google Chrome: presione Ctrl+Shift+R (⌘+Shift+R en Mac)
- Internet Explorer/Edge: mantenga presionada Ctrl mientras pulsa Actualizar, o presione Ctrl+F5
- Opera: Presiona Ctrl+F5.
//<nowiki>
/** initListingTools v1.0, 2021-11-06
Initialization of listing editor and listing info
Original author: Roland Unger
Support of desktop and mobile views
Documentation: https://de.wikivoyage.org/wiki/Wikivoyage:initListingTools.js
License: GPL-2.0+, CC-by-sa 3.0
*/
( function( $, mw ) {
'use strict';
var initListingTools = function() {
// scripts' page names
var scripts = {
listingEditor: 'MediaWiki:ListingEditor.js',
listingInfo: 'MediaWiki:ListingInfo.js'
};
// allowed namespaces for Listing Editor
var allowedNamespaces = [
0, // Main
2, // User
4, // Wikivoyage
];
// options for module import
var options = [
{
page: 'Module:Marker utilities/Types', // name of module to import
index: 'type', // name of key field
start: /^.*types *= *{/g, // to remove from start
end: /,? *},? *} *$/g, // to remove at the end
label: 'label', // second sort key
alias: 'alias', // alias for index
arrayName: 'types', // name of the new array
defaultArray: [
{ 'type': 'area', group: 'area', label: 'área' },
{ 'type': 'buy', group: 'buy', label: 'comprar' },
{ 'type': 'do', group: 'do', label: 'hacer' },
{ 'type': 'drink', group: 'drink', label: 'beber' },
{ 'type': 'eat', group: 'eat', label: 'comer' },
{ 'type': 'go', group: 'go', label: 'ir' },
{ 'type': 'other', group: 'other', label: 'otro' },
{ 'type': 'populated', group: 'populated', label: 'habitadas' },
{ 'type': 'see', group: 'see', label: 'ver' },
{ 'type': 'sleep', group: 'sleep', label: 'dormir' },
{ 'type': 'view', group: 'view', label: 'vista' },
]
},
{
page: 'Module:Marker utilities/Groups',
index: 'group',
start: /^.*groups *= *{/g,
end: /,? *},? *} *$/g,
label: 'label',
alias: 'alias',
arrayName: 'groups',
defaultArray: [
{ group: 'area', label: 'área', color: '#0000FF' },
{ group: 'buy', label: 'comprar', color: '#008080' },
{ group: 'do', label: 'hacer', color: '#808080' },
{ group: 'drink', label: 'beber', color: '#000000' },
{ group: 'eat', label: 'comer', color: '#D2691E' },
{ group: 'go', label: 'ir', color: '#A52A2A' },
{ group: 'other', label: 'otro', color: '#228B22' },
{ group: 'populated', label: 'habitadas', color: '#0000FF' },
{ group: 'see', label: 'ver', color: '#4682B4' },
{ group: 'sleep', label: 'dormir', color: '#000080' },
{ group: 'view', label: 'vista', color: '#4169E1' },
]
},
{
page: 'Module:VCard/Subtypes',
index: 'type',
start: /^.* f *= *{/g,
end: /,? *} *, *g *=.*$/g,
sortKey: 'sortkey', // first sort key
label: 'n', // second sort key
arrayName: 'subtypes',
defaultArray: [
{ 'type': 'budget', g: 1, w: '', n: '', f: '' },
{ 'type': 'midrange', g: 1, w: '', n: '', f: '' },
{ 'type': 'upmarket', g: 1, w: '', n: '', f: '' },
]
},
{
page: 'Module:VCard/Cards',
index: '', // only import, no rearranging
start: /^ *return *{/g,
end: /,? *} *$/g,
arrayName: 'payments',
defaultArray: {}
},
{
page: 'Module:Hours/i18n',
index: '',
start: /^.*dateIds *= *{/g,
end: /,? *},? *} *$/g,
arrayName: 'hours',
defaultArray: {}
},
{
page: 'Module:VCard/Qualifiers',
index: '',
start: /^.*labels *= *{/g,
end: /,? *},? *} *$/g,
arrayName: 'qualifiers',
defaultArray: {}
},
{
page: 'Module:CountryData/Currencies',
index: '',
start: /^ *return *{/g,
end: /,? *} *$/g,
arrayName: 'currencies',
defaultArray: {}
}
];
// data: data array from module
// item: single item from options array
// isDefault: data are defaults from options array
var analyzeAndCopyData = function( data, item, isDefault ) {
var i, dataItem;
// adding missing label from index
for ( i = 0; i < data.length; i++ ) {
dataItem = data[ i ];
dataItem[ item.label ] = dataItem[ item.label ] || '';
if ( dataItem[ item.label ] === '' ) {
if ( typeof dataItem[ item.alias ] === 'undefined' )
dataItem[ item.label ] = dataItem[ item.index ].replace( /_/g, ' ' );
else
if ( typeof( dataItem[ item.alias ] ) === 'string' )
dataItem[ item.label ] = dataItem[ item.alias ].replace( /_/g, ' ' );
else if ( dataItem[ item.alias ][ 0 ] )
dataItem[ item.label ] = dataItem[ item.alias ][ 0 ].replace( /_/g, ' ' );
}
}
// sorting by label in alphabetic order
data.sort( function( a, b ) {
if ( item.sortKey ) {
a = a[ item.sortKey ] || a[ item.label ];
b = b[ item.sortKey ] || b[ item.label ];
} else {
a = a[ item.label ];
b = b[ item.label ];
}
return a.localeCompare( b );
} );
// copying
if ( isDefault ) {
// copy only if window.ListingEditor.array is empty
if ( typeof window.ListingEditor[ item.arrayName ] === 'undefined' ||
window.ListingEditor[ item.arrayName ].length < 1 ) {
window.ListingEditor[ item.arrayName ] = [].concat( data );
}
} else {
window.ListingEditor[ item.arrayName ] = [].concat( data );
}
};
// item: item from options array
var getDataFromSingleModule = function( item ) {
return $.ajax( {
type: 'GET',
url: mw.util.wikiScript( '' ),
data: { title: item.page, action: 'raw', ctype: 'text/plain' },
timeout: 3000,
dataType: 'text'
} ).done( function( data ) {
data = data.replace( /\-\-.*\n/g, '' ) // remove comments
.replace( /[\s+\t+]/gm, ' ' ); // remove line breaks and tabs
if ( item.index !== '' )
// convert to (sortable) array
data = data.replace( item.start, '[' ) // delete beginning
.replace( item.end, ']' ) // delete end
.replace( /([,{]) *(wd|alias) *= *\{([^}]*)\}/g, '$1 "$2": [$3]' )
.replace( /( *\[ *")([\w\-]+)(" *\] *= *\{)/g, '{ "' + item.index + '": "$2", ' )
.replace( /( *)([\w\-]+)( *= *\{)/g, '{ "' + item.index + '": "$2", ' )
.replace( /(, *)([\w\-]+)( *=)/g, ', "$2":' );
else
// keep as object
data = data.replace( item.start, '{' ) // delete beginning
.replace( item.end, '}' ) // delete end
.replace( /( *\[ *")([\w\-]+)(" *\] *= *)/g, '"$2":' )
.replace( /([,\{]) *([\w\-]+)( *=)/g, '$1 "$2":' );
// check if data string is valid JSON
var isDefault = false;
try {
data = JSON.parse( data );
} catch ( e ) {
// invalid JSON
data = item.defaultArray;
isDefault = true;
console.log( e.message + ', data: ' + data );
}
if ( item.index !== '' )
analyzeAndCopyData( data, item, isDefault );
else
window.ListingEditor[ item.arrayName ] = data;
} ).fail( function() {
var data = item.defaultArray;
if ( item.index !== '' )
analyzeAndCopyData( data, item, true );
else
window.ListingEditor[ item.arrayName ] = data;
} );
};
var loadEditor = function() {
mw.loader.using( [ 'mediawiki.util', 'mediawiki.api', 'jquery.ui', 'jquery.chosen' ] ).then( function() {
mw.loader.load( '/w/index.php?title=' + scripts.listingEditor + '&action=raw&ctype=text/javascript' );
});
};
var getDataFromModules = function() {
var promiseArray = [], i;
// mw already exists but maybe not the ListingEditor object
if ( typeof window.ListingEditor === 'undefined' )
window.ListingEditor = {};
for ( i = 0; i < options.length; i++ )
promiseArray.push( getDataFromSingleModule( options[ i ] ) );
// wait for getting all external data
var isIE11 = !!window.MSInputMethodContext && !!document.documentMode;
if ( isIE11 )
$.when.apply( $, promiseArray ).then( function() {
loadEditor();
} );
else
if ( typeof Promise !== 'undefined' )
Promise.all( promiseArray )
.then( function() {
loadEditor();
} )
.catch( function() {
loadEditor();
// error warning
} );
return;
};
// *********************************************************************
// getting JSON object from Wikidata search
var ajaxSearch = function( url, data, success ) {
data.format = 'json';
$.ajax( {
url: url,
data: data,
dataType: 'jsonp',
success: success,
cache: false, // it will force requested pages not to be cached by
// the browser in case of script and jsonp data types
timeout: 3000
} );
};
// parse jsonObj for suboject with index id
var parseJsonEntitiesObj = function( jsonObj, id ) {
if ( !jsonObj || !jsonObj.entities || !jsonObj.entities[ id ] )
return null;
else
return jsonObj.entities[ id ];
};
// getting first value of a set of Wikidata statements
var getWikidataValue = function( jsonObj, id, property ) {
var entity = parseJsonEntitiesObj( jsonObj, id );
if ( !entity || !entity.claims || !entity.claims[ property ] )
return null;
var statements = entity.claims[ property ];
if ( !statements || statements.length < 1 || !statements[ 0 ].mainsnak
|| !statements[ 0 ].mainsnak.datavalue )
return null;
else
return statements[ 0 ].mainsnak.datavalue.value;
};
// adding currency, country calling code and local calling code to
// body-tag data attributes for use in listing editor
var addDataToBodyTag = function() {
var data, i, id, success, url, value;
// add wv-user-login class if user is logged-in
var body = $( 'body' );
if ( mw.config.get( 'wgUserName' ) )
body.addClass( 'wv-user-login' );
// copying data-currency data-country-calling-code, etc. from
// indicator or listings to body tag for use in listing editor
var dataTags = $( '.wv-coord-indicator' );
if ( !dataTags.length || dataTags.attr( 'data-country' ) === undefined )
dataTags = $( '.vCard' );
var list = [ 'data-currency', 'data-country-calling-code', 'data-lang', 'data-lang-name', 'data-dir', 'data-trunk-prefix' ];
for ( i = 0; i < list.length; i++ ) {
data = dataTags.attr( list [ i ] ) || '';
if ( data !== '' )
body.attr( list [ i ], data );
}
// copying local calling code from Wikidata to body tag
// if Wikidata id exists
id = mw.config.get( 'wgWikibaseItemId' );
if ( id ) {
url = '//www.wikidata.org' + '/w/api.php';
data = {
action: 'wbgetentities',
ids: id,
languages: mw.config.get( 'wgPageContentLanguage' ),
};
success = function( jsonObj ) {
value = getWikidataValue( jsonObj, id, 'P473' );
if ( value )
body.attr( 'data-local-calling-code', value );
};
ajaxSearch( url, data, success );
}
};
// *********************************************************************
/** Return false if the current page should not enable the listing editor.
Examples where the listing editor should not be enabled include talk
pages, edit pages, history pages, etc.
*/
var checkIfAllowed = function() {
var namespace = mw.config.get( 'wgNamespaceNumber' );
if ( !allowedNamespaces.includes( namespace )
|| mw.config.get( 'wgAction' ) != 'view' || $( '#mw-revision-info' ).length
|| mw.config.get( 'wgCurRevisionId' ) != mw.config.get( 'wgRevisionId' )
|| !mw.config.get( 'wgRelevantPageIsProbablyEditable' )
|| $( '#ca-viewsource' ).length )
return false;
else
return true;
};
var initEditor = function() {
var suppressLE = ( window.suppressListingEditor ) ?
window.suppressListingEditor : false;
if ( !suppressLE )
getDataFromModules();
};
var initInfo = function() {
mw.loader.load( '/w/index.php?title=' + scripts.listingInfo + '&action=raw&ctype=text/javascript' );
};
// *********************************************************************
// support of Skype links. Skype protocol is not supported by the
// Mediawiki software, and the link is to be added later
var addSkypeLinks = function() {
var p, t;
$( '.listing-skype-link' ).each( function() {
p = $( this );
t = p.text();
p.html( '<a href="skype:' + t + '">' + t.replace( /\?.*$/, '' ) + '</a>' );
});
};
var init = function() {
addDataToBodyTag();
addSkypeLinks();
if ( checkIfAllowed() ) {
initEditor();
initInfo();
}
// in future: creation of edit and info links
};
return { init: init };
} ();
$( initListingTools.init );
} ( jQuery, mediaWiki ) );
// </nowiki>