MediaWiki:Gadget-term-preview.js: Różnice pomiędzy wersjami

Z Wikisłownika – wolnego słownika wielojęzycznego
Usunięta treść Dodana treść
zmiana lokalizacji wezla HTML dla elementu popup, aby pobierano te sama wlasciwosc font-style co dla zawartosci hasla (w skorce Vector czcionka popup jest zauwazalnie wieksza)
IE/Edge nie wspiera [].flatMap
Linia 55: Linia 55:
secondLevel = 1;
secondLevel = 1;
$currHeader = $currTerms;
$currHeader = $currTerms;
}
}

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap
function flatMap( arr, callback, thisArg ) {
if ( 'flatMap' in Array.prototype ) {
return Array.prototype.flatMap.call( arr, callback, thisArg );
} else {
return arr.map( callback, thisArg ).reduce( function ( acc, val ) {
return acc.concat( val );
}, [] );
}
}
}
}
Linia 63: Linia 74:
return capture !== undefined;
return capture !== undefined;
} ).map( function ( group ) {
} ).map( function ( group ) {
return group.split( ',' ).flatMap( function ( subgroup ) {
return flatMap( group.split( ',' ), function ( subgroup ) {
return Number( subgroup ) || expandRange( subgroup ) || 0;
return Number( subgroup ) || expandRange( subgroup ) || 0;
} );
} );

Wersja z 01:19, 15 lis 2019

var exports = {},
	termsStorage = {},
	reInnerCapture = /^\((.+)\)$/,
	reSplit = / *, +/,
	reMain = /(\d+(?:[-–,\d]+)?)/,
	reFull = new RegExp( mw.format( '^$1(?:\\.$1)?$', reMain.source ) ),
	reRange = /^(\d+)[-–](\d+)$/,
	reTermNum = /^\((\d+)\.(\d+)\)$/,
	reTrailingSemicolon = /[\s;]+$/,
	$contentNode = $();

function parseTerms( $entryPoint, localTerms ) {
	var $currTerms, currTerm,
		$currHeader = $entryPoint,
		firstLevel = 1,
		secondLevel = 1;
	
	while ( true ) {
		$currHeader = $currHeader.next( 'p' );
		$currTerms = $currHeader.next( 'dl' );
		
		if (
			!$currHeader.length || !$currHeader.hasClass( 'fldt-znaczenia' ) ||
			!$currTerms.length
		) {
			break;
		}
		
		currTerm = {
			header: $currHeader,
			terms: [],
			valid: true
		};
		
		$currTerms.children( 'dd' ).each( function ( i, dd ) {
			var $dd = $( dd ),
				$num = $dd.find( '.term-num' ).first(),
				matches = reTermNum.exec( $num.text() );
			
			if (
				!$num.length || matches === null ||
				Number( matches[ 1 ] ) !== firstLevel ||
				Number( matches[ 2 ] ) !== secondLevel
			) {
				currTerm.valid = false;
				return false;
			}
			
			currTerm.terms.push( $dd );
			secondLevel++;
		} );
		
		localTerms.push( currTerm );
		firstLevel++;
		secondLevel = 1;
		$currHeader = $currTerms;
	}
}

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap
function flatMap( arr, callback, thisArg ) {
	if ( 'flatMap' in Array.prototype ) {
		return Array.prototype.flatMap.call( arr, callback, thisArg );
	} else {
		return arr.map( callback, thisArg ).reduce( function ( acc, val ) {
			return acc.concat( val );
		}, [] );
	}
}

function parseNum( text ) {
	return text.replace( reInnerCapture, '$1' ).split( reSplit ).map( function ( val ) {
		return ( reFull.exec( val ) || [] ).splice( 1 ).filter( function ( capture ) {
			return capture !== undefined;
		} ).map( function ( group ) {
			return flatMap( group.split( ',' ), function ( subgroup ) {
				return Number( subgroup ) || expandRange( subgroup ) || 0;
			} );
		} );
	} ).filter( function ( el ) {
		return el.length && el.every( function ( ell ) {
			return ell.length;
		} );
	} );
}

function expandRange( expr ) {
	var first, last,
		m = reRange.exec( expr );
	
	if ( m === null ) {
		return null;
	}
	
	first = Number( m[ 1 ] );
	last = Number( m[ 2 ] );
	
	// https://stackoverflow.com/a/20066663
	return Array.apply( null, { length: last + 1 } ).map( Number.call, Number ).slice( first );
}

function selectTermEls( nums, termsArr ) {
	return nums[ 0 ].reduce( function ( $obj, lvl ) {
		var termObj = termsArr[ lvl - 1 ];
		
		if ( !termObj.valid ) {
			return $obj;
		}
		
		$obj = $obj.add( termObj.header );
		
		if ( nums.length === 1 ) {
			termObj.terms.forEach( function ( term ) {
				$obj = $obj.add( term );
			} );
		} else {
			nums[ 1 ].forEach( function ( lvl2 ) {
				$obj = $obj.add( termObj.terms[ lvl2 - 1 ] );
			} );
		}
		
		return $obj;
	}, $() );
}

function populateStorage( code ) {
	var selFmt = 'dl:has(dt.lang-$1.fldt-znaczenia)',
		$entryPoint = $( mw.format( selFmt, code ) ),
		localTerms = termsStorage[ code ] = [];
	
	if ( $entryPoint.length ) {
		parseTerms( $entryPoint, localTerms );
	}
	
	return localTerms;
}

function makeContent( $terms ) {
	var html = '',
		startDefinition = false;
	
	$terms.each( function ( i, el ) {
		var $el = $( el ),
			isDefinition = $el.is( 'dd' );
		
		if ( !isDefinition ) {
			if ( html !== '' && !startDefinition ) {
				html += '</dl>';
			}
			
			html += $el.get( 0 ).outerHTML;
			startDefinition = true;
		} else {
			if ( startDefinition ) {
				html += '<dl>';
				startDefinition = false;
			}
			
			html += $el.get( 0 ).outerHTML;
		}
	} );
	
	return $( html )
		.find( '.reference' ).remove().end() // przypisy
		.find( 'dd' ).contents().filter( function () {
			return this.nodeType === Node.TEXT_NODE;
		} ).each( function () {
			var $this = $( this ),
				$next = $this.next();
				
				// szablony 'wikipedia', 'Gloger' itp. oraz poprzedzający je średnik
				if ( $next.is( '.term-preview-ignore' ) ) {
					$next.remove();
					$this.replaceWith( function () {
						return this.textContent.replace( reTrailingSemicolon, '' );
					} );
				}
		} ).end().end().end();
}

// https://stackoverflow.com/a/33979503
function isInViewport( $el ) {
	var top_of_element = $el.offset().top,
		bottom_of_element = $el.offset().top + $el.outerHeight(),
		$window = $( window ),
		bottom_of_screen = $window.scrollTop() + $window.innerHeight(),
		top_of_screen = $window.scrollTop();
	
	return bottom_of_screen > top_of_element && top_of_screen < bottom_of_element;
}

exports.enablePreview = function ( $num, code ) {
	var $terms, popup;
	
	if ( !( code in termsStorage ) && !populateStorage( code ).length ) {
		return;
	}
	
	$terms = parseNum( $num.text() ).reduce( function ( $acc, nums ) {
		return $acc.add( selectTermEls( nums, termsStorage[ code ] ) );
	}, $() );
	
	if ( !$terms.length ) {
		return;
	}
	
	$num.on( 'click', function ( e ) {
		$( '.term-selected' ).removeClass( 'term-selected' );
		
		if ( !isInViewport( $terms.first() ) ) {
			$terms.first().get( 0 ).scrollIntoView();
		}
		
		$terms.addClass( 'term-selected' );
		
		$( document ).one( 'click', function ( e ) {
			if ( !$( e.target ).closest( $terms ).length ) {
				 $terms.removeClass( 'term-selected' );
			}
		} );
		
		return false;
	} ).on( 'mouseenter focus', function ( e ) {
		popup = new OO.ui.PopupWidget( {
			$content: makeContent( $terms ),
			$floatableContainer: $( this ),
			padded: true,
			align: 'forwards',
			classes: [ 'term-preview-container' ]
		} );
		$contentNode.append( popup.$element );
		popup.toggle( true );
	} ).on( 'mouseleave blur', function ( e ) {
		popup.$element.remove();
	} ).addClass( 'term-lookup' );
};

mw.hook( 'wikipage.content' ).add( function ( $content ) {
	termsStorage = {};
	$contentNode = $content;
} );

module.exports = exports;