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)
  • Edge: mantenga presionada Ctrl mientras pulsa Actualizar, o presione 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>