MediaWiki:Gadget-hovercards-local.js

Z Wikisłownika – wolnego słownika wielojęzycznego

Uwaga: aby zobaczyć zmiany po opublikowaniu, może zajść potrzeba wyczyszczenia pamięci podręcznej przeglądarki.

  • Firefox / Safari: Przytrzymaj Shift podczas klikania Odśwież bieżącą stronę, lub naciśnij klawisze Ctrl+F5, lub Ctrl+R (⌘-R na komputerze Mac)
  • Google Chrome: Naciśnij Ctrl-Shift-R (⌘-Shift-R na komputerze Mac)
  • Internet Explorer / Edge: Przytrzymaj Ctrl, jednocześnie klikając Odśwież, lub naciśnij klawisze Ctrl+F5
  • Opera: Naciśnij klawisze Ctrl+F5.
/**
 * Modyfikacja kodu źrodłowego [[:mw:Beta Features/Hovercards]] na potrzeby polskiej wersji Wikisłownika
 * Licencja: GNU GENERAL PUBLIC LICENSE, Version 2, June 1991
 * Autor przeróbki: [[User:Peter Bowman]]
 */

mw.popups.plwikt = {
	lang2code: mw.config.get( 'lang2code' )
};

mw.popups.plwikt.processExtract = function ( text ) {
	return text
		// usuwanie przypisów
		.replace( /<ref.+?(\/|ref)>/g, '' )
		// zamiana pogrubień na cudzysłowy (np. w czasownikach zwrotnych)
		.replace( /'''(.+?)'''/g, '„$1”' )
		// wykrywanie nagłówka znaczeń; pogrubienie i pochylenie
		.replace( /\n[']{0,2}\{\{(.*?)(\|[^\}]+)?\}\}[']{0,2}\n/g, '\n<i><b>$1</b></i>\n' )
		.replace( /\n''(.+?)''/g, '\n<i><b>$1</b></i>' )
		// kursywa w definicji
		.replace( /''(.+?)''/g, '<i>$1</i>' )
		// usuwa tekst po średniku (np. linki do Wikipedii)
		.replace( /;[^\n]+\n/g, '\n' )
		// obsługa szablonów "zob", "(nie)dokonany od", "odczasownikowy od"
		.replace( /\{\{zob\|([^\}]+)\}\}/g, '<i>zob.</i> $1' )
		.replace( /\{\{(nie)?dokonany od\|([^\}]+)\}\}/g, '<i>aspekt $1dokonany od</i> $2' )
		.replace( /\{\{odczasownikowy od\|((nie)\|)?([^\}]+)\}\}/g, '<i>rzecz. odczasownikowy od</i> $2 $3' )
		// wywołania szablonów z użyciem jednego lub więcej parametrów zastępuje wielokropkiem w nawiasach
		.replace( /\{\{[^\}]+\|.*?\}\}/g, '(…)' )
		// obsługa skrótów
		.replace( /\{\{([^\}]+)\}\}/g, '<i>$1.</i>' )
		// wcięcia na początku definicji
		.replace( /\n: \(/g, '\n&nbsp;(' )
		// nowa linia
		.trim()
		.replace( /\n/g, '<br>' )
		// obsługa linków, zaczerpnięte z Linker::formatLinksInComment() w Linker.php
		.replace(
			/\[\[:?([^\]\|]+)(?:\|((?:\]?[^\]\|])+))*\]\]([^\[]*)/g,
			function ( match, link, text, trail ) {
				return ( text || link ) + trail;
			}
		);
};

mw.popups.plwikt.parsePage = function ( page, lang ) {
	var pagecontent, langheader, langend, langsection, defheader, declheader, defs, hasimage;
	
	pagecontent = page.revisions[ 0 ].content;
	langheader = pagecontent.search( new RegExp(
		'\\{\\{(język )?' +
		lang.replace( '(', '\\(' ).replace( ')', '\\)' )
	) );
	
	if ( langheader === -1 ) {
		return true;
	}

	langend = pagecontent.indexOf( '\n== ', langheader );
	langsection = pagecontent.slice( langheader, ( langend === -1 )
		? pagecontent.length
		: langend
	);
	defheader = langsection.indexOf( '{' + '{znaczenia}}' );
	declheader = langsection.indexOf( '{' + '{odmiana}}', defheader );
	
	if ( defheader === -1 || declheader === -1 ) {
		return false;
	}
	
	defs = langsection.slice( defheader + 13, declheader );
	defs = mw.popups.plwikt.processExtract( defs );

	initialsections = langsection.slice( 0, defheader ).replace( / /g, '_' );
	
	if (
		page.pageimage &&
		initialsections.indexOf( '[[Plik:' + decodeURI( page.pageimage ) ) !== -1
	) {
		hasimage = true;
	}
	
	return {
		defs: defs,
		hasimage: !!hasimage
	};
};

mw.popups.plwikt.renderShort = function ( link, event, href, short_wrapper ) {
	var redirect, innerHtml, $div, $extract, $icons;
	
	mw.popups.render.currentLink = link;
	link.on( 'mouseleave blur', mw.popups.render.leaveInactive );
	
	if ( link.hasClass( 'new' ) ) {
		redirect = '';
	} else if ( decodeURI( href ).indexOf( 'Aneks:Skróty' ) !== -1 ) {
		redirect = 'kliknij, aby zobaczyć listę skrótów używanych w Wikisłowniku';
	} else {
		redirect = mw.format(
			'skrót przekierowuje do strony<br><i>$1</i>',
			decodeURI( href.replace( /^\/wiki\/(.+?)(?:#.*)?$/, '$1' ) )
				.replace( /_/g, ' ' )
				// [[Specjalna:Niezmienny link/4318644#Typografia nazw stron (półpauza)]]
				.replace( / - /g, ' – ' )
		);
	}
	
	innerHtml = mw.format(
		'<h3><i>$1</i></h3>$2',
		short_wrapper.data( 'title' ),
		redirect
	);
	
	$extract = $( '<a>' )
		.attr( 'href', href )
		.addClass( 'mwe-popups-extract' )
		.html( innerHtml )
		.css( {
			'padding-bottom': 0,
			'margin-bottom': 0
		} );
	
	$icons = $( '<div>' )
		.append( $( '<a>' )
			.addClass( 'mwe-popups-icon mwe-popups-settings-icon' )
		)
		.css( 'padding-bottom', 0 );
	
	$div = $( '<div>' ).append( $extract, $icons );
	
	if ( mw.popups.render.renderers.article.surveyLink ) {
		$icons.append( $( '<a>' )
			.attr( 'href', mw.popups.render.renderers.article.surveyLink )
			.attr( 'target', '_blank' )
			.attr( 'title', mw.message( 'popups-send-feedback' ) )
			.addClass( 'mwe-popups-icon mwe-popups-survey-icon' )
		);
	}
	
	// potrzebne dla funkcji openPopup
	mw.popups.render.cache[ href ] = {
		popup: $div,
		getOffset:  mw.popups.render.renderers.article.getOffset,
		getClasses: mw.popups.render.renderers.article.getClasses,
		process:    mw.popups.render.renderers.article.processPopup,
		settings:   {
			title: '_short',
			tall: false,
			thumbnail: false
		}
	};

	mw.popups.render.openPopup( link, event );
	delete mw.popups.render.cache[ href ]; // gc?
};

mw.popups.plwikt.getLangName = function ( fragment ) {
	var decoded, longname;
	
	if ( fragment.indexOf( '_' ) !== -1 ) {
		decoded = decodeURIComponent( fragment.replace( /_/g, '%20' ).replace( /\./g, '%' ) );
		return decoded.match( /\((język )?(.*?)\)/, '$2' )[ 2 ] || null;
	} else {
		for ( longname in mw.popups.plwikt.lang2code ) {
			if ( mw.popups.plwikt.lang2code[ longname ] === fragment ) {
				return longname;
			}
		}
	}
};

mw.popups.plwikt.oldArticleCreatePopup = mw.popups.render.renderers.article.createPopup;

mw.popups.plwikt.externalQueryData = {
	origin:      location.origin,
	prop:        [ 'info', 'extracts', 'pageimages', 'revisions' ],
	formatversion: 2,
	redirects:   true,
	exintro:     true,
	exsentences: 5,
	// there is an added geometric limit on .mwe-popups-extract
	// so that text does not overflow from the card
	explaintext: true,
	piprop:      'thumbnail',
	//pithumbsize: 300,
	rvprop:      'timestamp',
	smaxage:     300,
	maxage:      300,
	uselang:     'content'
};

mw.popups.plwikt.internalQueryData = {
	prop:        [ 'info', 'pageimages', 'revisions' ],
	formatversion: 2,
	redirects:    true,
	//pithumbsize:  300,
	rvprop:      [ 'timestamp', 'content' ],
	smaxage:     300,
	maxage:      300,
	uselang:     'content'
};

mw.popups.plwikt.renderExternalLink = function ( link, event ) {
	mw.popups.render.currentLink = link;
	link.on( 'mouseleave blur', mw.popups.render.leaveInactive );
	
	if ( mw.popups.render.cache[ link.attr( 'href' ) ] ) {
		mw.popups.render.openTimer = mw.popups.render.wait( mw.popups.render.POPUP_DELAY )
			.done( function () {
				mw.popups.render.openPopup( link, event );
			} );
	} else {
		mw.popups.render.openTimer = mw.popups.render.wait( mw.popups.render.API_DELAY )
			.done( function () {
				var cachePopup = mw.popups.render.renderers.article.init( link, true );
				mw.popups.render.openTimer = mw.popups.render.wait( mw.popups.render.POPUP_DELAY - mw.popups.render.API_DELAY );
				
				$.when( mw.popups.render.openTimer, cachePopup ).done( function () {
					mw.popups.render.openPopup( link, event );
				} );
			} );
	}
};

mw.popups.plwikt.createNewSectionPopup = function ( title, lang ) {
	var formattedTitle, $link, innerHtml;
	
	formattedTitle = /^[ \u0530-\uFFFF]+$/.test( title )
		? title
		: '<i>' + title + '</i>';
	
	$link = $( '<a>' )
		.attr( 'href', mw.util.getUrl( title, { action: 'edit' } ) )
		.text( 'tutaj' );

	innerHtml = mw.format(
		'brak sekcji językowej <i>$1</i> dla strony $2<br><br><i>kliknij <u>$3</u>, aby ją utworzyć!</i>',
		lang,
		formattedTitle,
		$link.prop( 'outerHTML' )
	);
	
	return $( '<div>' ).append( $( '<p>' )
		.addClass( 'mwe-popups-extract' )
		.html( innerHtml )
	);
};

// z ext.popups.renderer.js

mw.popups.render.render = function ( link, event ) {
	var short_href, short_wrapper, // ZMIANY
		href = link.attr( 'href' ), // ZMIANY
		fragmentindex = href.indexOf( '#' ),
		fragment = href.slice( fragmentindex + 1 ),
		lang = null;
	
	// ZMIANY - gadget false-blue-links.js
	if ( link.hasClass( 'mw-false-blue' ) ) {
		return;
	}
	
	// This will happen when the mouse goes from the popup box back to the
	// anchor tag. In such a case, the timer to close the box is cleared.
	if (
		mw.popups.render.currentLink &&
		mw.popups.render.currentLink[0] === link[0]
	) {
		if ( mw.popups.render.closeTimer ) {
			mw.popups.render.closeTimer.abort();
		}
		return;
	}
	
	// If the mouse moves to another link (we already check if its the same
	// link in the previous condition), then close the popup.
	if ( mw.popups.render.currentLink ) {
		mw.popups.render.closePopup();
	}
	
	// Ignore if its meant to call a function
	// TODO: Remove this when adding reference popups
	if ( href === '#' ) { // ZMIANY
		return;
	}
	
	// ZMIANY - obsługa linków do innych projektów
	if ( link.hasClass( 'extiw' ) ) {
		mw.popups.plwikt.renderExternalLink( link, event );
		return;
	}
	
	// ZMIANY - obsługa skrótów
	short_wrapper = link.children( '.short-wrapper' );
	
	if ( short_wrapper.length ) {
		mw.popups.render.wait( mw.popups.render.POPUP_DELAY ).done( function () {
			mw.popups.plwikt.renderShort( link, event, href, short_wrapper );
		} );
		return;
	}
	
	// ZMIANY - ignorowanie linków bez określonej sekcji
	if ( fragmentindex === -1 ) {
		return;
	}
	
	// ZMIANY - otrzymanie nazwy sekcji językowej
	lang = mw.popups.plwikt.getLangName( fragment );
	
	if ( !lang ) {
		return;
	}
	
	// ZMIANY - obsługa selflinków z Gadget-section-links.js usuwa atrybut "title"
	if ( !link.data( 'title' ) ) {
		link.data( 'title', decodeURI( href.slice( href.lastIndexOf( '/' ) + 1 ), fragmentindex ) );
	}
	
	mw.popups.render.currentLink = link;
	link.on( 'mouseleave blur', mw.popups.render.leaveInactive );
	
	short_href = href.slice( 0, fragmentindex ); // ZMIANY

	if ( mw.popups.render.cache[ short_href ] ) { // ZMIANY
		if ( !mw.popups.render.cache[ href ] ) {
			mw.popups.render.cache[ href ] = {};
			mw.popups.render.cache[ href ].popup = mw.popups.render.renderers.article.createPopup( // ZMIANY
				mw.popups.render.cache[ short_href ].request,
				href,
				lang
			);
			mw.popups.render.cache[ href ].getOffset = mw.popups.render.renderers.article.getOffset;
			mw.popups.render.cache[ href ].getClasses = mw.popups.render.renderers.article.getClasses;
			mw.popups.render.cache[ href ].process = mw.popups.render.renderers.article.processPopup;
		}
		
		if ( mw.popups.render.cache[ href ].popup ) { // ZMIANY
			mw.popups.render.openTimer = mw.popups.render.wait( mw.popups.render.POPUP_DELAY )
				.done( function () {
					mw.popups.render.openPopup( link, event );
				} );
		}
	} else {
		// Wait for timer before making API queries and showing hovercard
		mw.popups.render.openTimer = mw.popups.render.wait( mw.popups.render.API_DELAY )
			.done( function () {
				// TODO: check for link type and call correct renderer
				// There is only one popup type so it isn't necessary right now
				var cachePopup = mw.popups.render.renderers.article.init( link, false, lang ); // ZMIANY
				
				mw.popups.render.openTimer = mw.popups.render.wait( mw.popups.render.POPUP_DELAY - mw.popups.render.API_DELAY );
				
				$.when( mw.popups.render.openTimer, cachePopup ).done( function () {
					if ( mw.popups.render.cache[ href ] && mw.popups.render.cache[ href ].popup ) { // ZMIANY
						mw.popups.render.openPopup( link, event );
					}
				} );
			} );
	}
};

// z ext.popups.renderer.article.js

mw.popups.render.renderers.article.init = function ( link, isExtiw, lang ) { // ZMIANY
	var site, title, // ZMIANY
		href = link.attr( 'href' ),
		short_href = null, // ZMIANY
		deferred = $.Deferred(),
		scaledThumbSize = 300 * $.bracketedDevicePixelRatio(),
		data = null,        // ZMIANY
		ajaxOptions = null; // ZMIANY
	
	// ZMIANY
	title = isExtiw
		? link.data( 'title' )
		: mw.popups.getTitle( href );
	
	if ( !title ) {
		return deferred.reject().promise();
	}
	
	// ZMIANY
	if ( isExtiw ) {
		data = mw.popups.plwikt.externalQueryData;
		data.titles = title.slice( title.indexOf( ':' ) + 1 );
		
		site = href.slice(
			href.indexOf( '://' ) + 3,
			href.indexOf( '.org/' )
		);
		
		ajaxOptions = {
			url:      mw.format( '//$1.org/w/api.php', site ),
			xhrFields: {
				withCredentials: true
			}
		};
	} else {
		data = mw.popups.plwikt.internalQueryData;
		data.titles = title;
	}
	
	data.pithumbsize = scaledThumbSize; // ZMIANY
	mw.popups.render.currentRequest = mw.popups.api.get( data, ajaxOptions ); // ZMIANY
	
	mw.popups.render.currentRequest.fail( deferred.reject );
	mw.popups.render.currentRequest.done( function ( re ) {
		var short_href;
		mw.popups.render.currentRequest = undefined;
	
		if ( // ZMIANY
			!re.query ||
			!re.query.pages ||
			( isExtiw && (
				!re.query.pages[ 0 ].extract ||
				re.query.pages[ 0 ].extract === ''
			) ) ||
			( !isExtiw && (
				!re.query.pages[ 0 ].revisions ||
				!re.query.pages[ 0 ].revisions.length ||
				!re.query.pages[ 0 ].revisions[ 0 ].content
			) )
		) {
			// Restore the title attribute and set flag
			// TODO: uwzględnić tu błędy podczas parsowania pola znaczeń
			if ( link.data( 'dont-empty-title' ) !== true ) {
				link
					.attr( 'title', link.data( 'title' ) )
					.removeData( 'title' )
					.data( 'dont-empty-title', true );
			}
			deferred.reject();
			return;
		}
		
		mw.popups.render.cache[ href ] = {};
		
		// ZMIANY
		if ( isExtiw ) {
			mw.popups.render.cache[ href ].popup = mw.popups.plwikt.oldArticleCreatePopup( re.query.pages[ 0 ], href );
		} else {
			short_href = href.slice( 0, href.indexOf( '#' ) );
			
			mw.popups.render.cache[ short_href ] = { request: re.query.pages[ 0 ] };
			mw.popups.render.cache[ href ].popup = mw.popups.render.renderers.article.createPopup( re.query.pages[ 0 ], href, lang );
		}
		
		mw.popups.render.cache[ href ].getOffset = mw.popups.render.renderers.article.getOffset;
		mw.popups.render.cache[ href ].getClasses = mw.popups.render.renderers.article.getClasses;
		mw.popups.render.cache[ href ].process = mw.popups.render.renderers.article.processPopup;
		
		deferred.resolve();
	} );
	
	return deferred.promise();
};

mw.popups.render.renderers.article.createPopup = function ( page, href, lang ) { // ZMIANY
	var $div, hasThumbnail, tall, parsed, $thumbnail, // ZMIANY
		thumbnail = page.thumbnail,
		timestamp = new Date( page.revisions[ 0 ].timestamp ),
		timediff = new Date() - timestamp,
		oneDay = 1000 * 60 * 60 * 24;
	
	// ZMIANY - analiza wikikodu
	parsed = mw.popups.plwikt.parsePage( page, lang );
	
	if ( typeof parsed !== 'object' ) {
		if ( parsed ) {
			mw.popups.render.cache[ href ].settings = {};
			return mw.popups.plwikt.createNewSectionPopup( page.title, lang );
		} else {
			return false;
		}
	}
	
	thumbnail = ( parsed.hasimage ) ? thumbnail : undefined;
	tall = thumbnail && thumbnail.height > thumbnail.width;
	$thumbnail = mw.popups.render.renderers.article.createThumbnail( thumbnail, tall );
	
	// createThumbnail returns an empty <span> if there is no thumbnail
	hasThumbnail = $thumbnail.prop( 'tagName' ) !== 'SPAN';
	
	$div = mw.template.get( 'ext.popups', 'preview.mustache' ).render( {
		langcode: page.pagelanguagehtmlcode,
		langdir: page.pagelanguagedir,
		href: href,
		isRecent: timediff < oneDay,
		lastModified: mw.message( 'popups-last-edited', moment( timestamp ).fromNow() ).text(),
		hasThumbnail: hasThumbnail
	} );
	
	if ( !hasThumbnail ) {
		tall = thumbnail = undefined;
	} else {
		$div.find( '.mwe-popups-discreet' ).append( $thumbnail );
	}
	$div.find( '.mwe-popups-extract' )
		.html( parsed.defs ); // ZMIANY
	if ( mw.popups.render.renderers.article.surveyLink ) {
		$div.find( 'footer' ).append(
			mw.popups.render.renderers.article.createSurveyLink(
				mw.popups.render.renderers.article.surveyLink
			)
		);
	}
	
	mw.popups.render.cache[ href ].settings = {
		'title': page.title,
		'tall': ( tall === undefined ) ? false : tall,
		'thumbnail': ( thumbnail === undefined ) ? false : thumbnail
	};
	
	return $div;
};

mw.hook( 'wikipage.content' ).add( function ( $content ) {
	var $allshorts, $extiw;
	
	if ( mw.popups.enabled ) {
		$allshorts = $content.find( '.short-container' );
		
		mw.popups.removeTooltips( $allshorts.find( '.short-wrapper' ) );
		mw.popups.setupTriggers( $allshorts.find( 'a' ) );
		
		$extiw = $content.find( 'a.extiw:not(.fldt-wymowa, .section-interwiki)' );
		
		mw.popups.removeTooltips( $extiw );
		mw.popups.setupTriggers( $extiw );
	}
} );