Користувач:Glovacki/infobox.js

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до навігації Перейти до пошуку

Увага: Після публікування слід очистити кеш браузера, щоб побачити зміни.

  • Firefox / Safari: тримайте Shift, коли натискаєте Оновити, або натисніть Ctrl-F5 чи Ctrl-Shift-R (⌘-R на Apple Mac)
  • Google Chrome: натисніть Ctrl-Shift-R (⌘-Shift-R на Apple Mac)
  • Internet Explorer / Edge: тримайте Ctrl, коли натискаєте Оновити, або натисніть Ctrl-F5
  • Opera: натисніть Ctrl-F5
( function ( mw, $ ) {
	var api;
	var wdApi;
	var loopCnt = 0;
	var blacklist = [];

	var addTemplate = function ( wikitext ) {
		api.postWithToken( 'csrf', {
			action: 'edit',
			title: mw.config.get( 'wgTitle' ),
			prependtext: wikitext + '\n',
			summary: 'додавання шаблона-карточки'
		} ).done( function ( data ) {
			window.location.reload();
		} );
	};

	var generateTemplate = function ( templateTitle ) {
		var wikitext = '{{' + templateTitle.replace( /^Шаблон:/, '' ) + '}}';

		api.get( {
			action: 'parse',
			prop: 'text',
			title: mw.config.get( 'wgTitle' ),
			text: wikitext
		} ).done( function ( data ) {
			if ( data.parse && data.parse.text ) {
				var $infobox = $( '<div>' )
					.append( $( data.parse.text['*'] ) )
					.find( '.infobox' );
				$contentText = mw.util.$content.find( '#mw-content-text' )
					.prepend( $infobox );

				var $indicatorTpl = $( '<a>' )
					.attr( 'href', mw.util.getUrl( templateTitle ) )
					.append( new OO.ui.IconWidget( {
						icon: 'code'
					} ).$element );

				var $indicatorAdd = $( '<a>' )
					.attr( 'href', '#' )
					.append( new OO.ui.IconWidget( {
						icon: 'add'
					} ).$element )
					.on( 'click', function ( e ) {
						e.preventDefault();
						addTemplate( wikitext );
					} );

				mw.util.$content.find( '.mw-indicators' )
					.append( $indicatorTpl )
					.append( $indicatorAdd );
			}
		} );
	};

	var getMainTemplateLinks = function ( templateIds, parentIds ) {
		// Запрос ссылок для элементов.
		wdApi.get( {
			action: 'wbgetentities',
			props: 'sitelinks',
			ids: templateIds
		} ).done( function ( data ) {
			var templateLinks = [];
			if ( data.success ) {
				for ( var i in data.entities ) {
					if ( !i.match( /^Q/ ) ) {
						return;
					}

					var sitelinks = data.entities[i].sitelinks;
					if ( !sitelinks ) {
						continue;
					}
					
					if ( sitelinks.ruwiki ) {
						templateLinks.push( sitelinks.ruwiki.title );
					}
				}
			}
			if ( templateLinks.length ) {
				console.log( 'Инфобоксы:', templateLinks );
				generateTemplate( templateLinks.shift() );
			} else {
				getMainTemplates( parentIds );
			}
		} );
	};

	/*
	 * Рекурсивный поиск шаблонов.
	 */
	var getMainTemplates = function ( parentIds, propertyIds ) {
		if ( ++loopCnt > 10 ) {
			mw.notify( 'Бесконечный цикл в Викиданных', 'error' );
			return;
		}

		if ( !parentIds.length ) {
			mw.notify( 'Для элемента не найден соответствующий шаблон-карточка', 'warn' );
			return;
		}

		// Запрос утверждений для элементов.
		wdApi.get( {
			action: 'wbgetentities',
			props: 'claims',
			ids: parentIds
		} ).done( function ( data ) {
			if ( data.success ) {
				var templateIds = [];
				var newParentIds = [];
				var isP31 = true;
				parentIds.forEach( function ( parentId) {
					blacklist.push( parentId );
				} );
				var pushEntityId = function ( claim, i ) {
					if ( claim.mainsnak &&
						claim.mainsnak.datavalue &&
						claim.mainsnak.datavalue.value
					) {
						if ( blacklist.indexOf( claim.mainsnak.datavalue.value.id ) === -1 ) {
							this.push( claim.mainsnak.datavalue.value.id );
						}
					}							
				};
				for ( var i in data.entities ) {
					if ( !i.match( /^Q/ ) ) {
						return;
					}

					var claims = data.entities[i].claims;
					if ( !claims ) {
						continue;
					}
					
					if ( claims.P1424 ) {
						claims.P1424.forEach( pushEntityId, templateIds );
					}
					
					propertyIds = propertyIds || [];
					propertyIds.push( 'P279' );
					var propertyId;
					propertyIds.forEach( function ( pId ) {
						if ( claims[pId] ) {
							if ( !propertyId ) {
								propertyId = pId;
							}
						} else if ( pId === 'P31' ) {
							isP31 = false;
						}
					} );
					if ( propertyId && claims[propertyId] ) {
						claims[propertyId].forEach( pushEntityId, parentIds );
					}
				}
				
				if ( templateIds.length ) {
					getMainTemplateLinks( templateIds, parentIds );
				} else if ( !isP31 ) {
					mw.notify( 'В элементе Викиданных не задано свойство «это частный случай понятия» (P31)', 'warn' );
				} else {
					getMainTemplates( parentIds );
				}
			}
		} );
	};
	
	/*
	 * Инициализация скрипта.
	 */
	var init = function () {
		if ( mw.config.get( 'wgAction' ) !== 'view' ||
			mw.config.get( 'wgNamespaceNumber' )
		) {
			return;
		}
		if ( mw.config.get( 'wgWikibaseItemId' ) === null ) {
			return;
		}

		var $infobox = mw.util.$content.find( '.infobox' );
		if ( $infobox.length ) {
			var $indicator = $( '<a>' )
				.attr( 'href', '#' )
				.append( new OO.ui.IconWidget( {
					icon: 'cancel'
				} ).$element )
				.on( 'click', function ( e ) {
					e.preventDefault();
					mw.util.$content.find( '.infobox' ).remove();
					init();
				} );
			mw.util.$content.find( '.mw-indicators' )
				.append( $indicator );
			return;
		}
		
		api = new mw.Api();
		wdApi = new mw.ForeignApi( '//www.wikidata.org/w/api.php' );
		getMainTemplates( [mw.config.get( 'wgWikibaseItemId' )], ['P106', 'P31'] );
	};

	$.when(
		$.ready,
		mw.loader.using( [
			'mediawiki.api',
			'mediawiki.ForeignApi',
			'mediawiki.util',
			'oojs-ui-widgets'
		] )
	).done( init );
}( mediaWiki, jQuery ) );