MediaWiki:Gadget-shiftrefs.js

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску
JS-код ниже относится к гаджету «Разместить ссылки на сноски над знаками препинания, а не перед (так.[1], а не так[1]. (править описание). Его использует около 600 учётных записей.

После сохранения или недавних изменений очистите кэш браузера.

// Copy from https://ru.wikipedia.org/wiki/Участник:Ignatus/shiftrefs.js
// Authors: https://ru.wikipedia.org/wiki/Участник:Ignatus/shiftrefs.js?action=history

/*************************************************************/
/*****      Сдвигает все ссылки на знаки препинания      *****/
/*************************************************************/
function lebedevrefs() {
	var diglasttext;
	var getsimpletext;
	diglasttext = function ( n ) {
		return n.lastChild ? diglasttext( n.lastChild ) : n;
	};
	getsimpletext = function ( n ) {
		return n.innerHTML.replace( /<(?:"(?:\\\\|\\"|\\[^"]|[^\\"])*"|'(?:\\\\|\\'|\\[^']|[^\\'])*'|[^"'>])+>/ig, '' ); //'
	};//innerText работает не везде
	var zone = document.getElementById( 'wikiPreview' ) || document.getElementById( 'bodyContent' )
		|| document.getElementById( 'mw_contentholder' ) || document.getElementById( 'article' );

	var alles = Array();
	{
		var j = zone.getElementsByTagName( '*' );
		for ( var i = 0; i < j.length; i++ ) {
			alles[ i ] = j[ i ];
		}
	}
	var getdots = /^([\s\S]*?)([.,…]*)$/;
	var i = 0;
	var f = function () {
		if ( i < alles.length ) {
			var ch = alles[ i ].childNodes;
			// Ищем последовательности элементов класса reference
			// а также рассматриваем ноды до и после них
			for ( var j = 0; j < ch.length; j++ ) {
				var l = 0;
				while ( j + l < ch.length // &&
					&& ( ch[ j + l ].nodeType == 1 ) // && // элемент
					&& /(^|\s)reference(\s|$)/i.test( ch[ j + l ].className )
				) {
					l++;
				}
				if ( l ) {//есть группа
					var grp = document.createElement( 'span' );
					for ( var k = 0; k < l; k++ ) {
						ch[ j ].style.position = 'relative';
						grp.appendChild( ch[ j ] );
						//alles[i].removeChild(ch[j]);//автоматом
					}
					if ( j < ch.length ) {
						alles[ i ].insertBefore( grp, ch[ j ] );
					} else {
						alles[ i ].appendChild( grp );
					}
					grp.style.whiteSpace = 'nowrap';
					var ppw = 0.;
					if ( j ) {
						if ( ch[ j - 1 ].nodeType == 3 ) { // текст
							var a = /^([\S\s]*\s)?(\S*?)([.,…]*)?$/.exec( ch[ j - 1 ].nodeValue );
							ch[ j - 1 ].nodeValue = a[ 1 ] || '';
							var b = document.createElement( 'span' );
							var t = document.createTextNode( a[ 3 ] || a[ 2 ] );
							b.appendChild( t );
							grp.insertBefore( b, grp.firstChild );
							if ( a[ 3 ] ) {
								b.style.marginRight = '-' + b.offsetWidth + 'px';
								t.nodeValue = a[ 2 ] + t.nodeValue;
							}
							ppw = b.offsetWidth;
						} else {// если предыдущий узел - элемент
							var lt = diglasttext( ch[ j - 1 ] );
							var a = getdots.exec( lt.nodeValue );
							if ( a[ 2 ] ) {//финишные точки выделяем
								lt.nodeValue = a[ 1 ];
								var b = document.createElement( 'span' );
								b.appendChild( document.createTextNode( a[ 2 ] ) );
								lt.parentNode.appendChild( b );
								ppw = b.offsetWidth;
								b.style.marginRight = '-' + ppw + 'px';
							}
							if ( /nowrap|pre$/.test( ch[ j - 1 ].style.whiteSpace ) || !/\s/.test( getsimpletext( ch[ j - 1 ] ) ) ) {
								//если его можно втащить в неразрывный текст, делаем это
								grp.insertBefore( ch[ j - 1 ], grp.firstChild );
								ppw += grp.firstChild.offsetWidth;
							}
						}//else
					}//if ( j )
					if ( grp.nextSibling ) {//Смотрим дальше, если текст, отрезаем начальную точку
						if ( grp.nextSibling.nodeType == 3 ) {
							var a = /^([.,…]*)([\s\S]*?)$/.exec( grp.nextSibling.nodeValue );
							if ( a[ 1 ] ) {
								grp.nextSibling.nodeValue = a[ 2 ];
								var b = document.createElement( 'span' );
								b.appendChild( document.createTextNode( a[ 1 ] ) );
								grpw = grp.offsetWidth;
								grp.appendChild( b );
								b.previousSibling.style.marginRight = ( ppw - grpw ) + 'px';
								b.previousSibling.style.position = 'relative';
								b.style.marginRight = ( grpw - ppw - b.offsetWidth ) + 'px';
							}//if(a[1])
						}//if( grp.nextSibling.nodeType==3 )
					}//if(grp.nextSibling)
				}//if(l)
			}//for(ch)
			i++;
			window.setTimeout( f, 0 );//обрабатываем действия пользователя, затем идём дальше
		} else {//(i>=alles.length)
			f = null;//помогаем мусорнице
		}//if(i<alles.length)
	};//f
	if ( alles.length ) {
		f();
	}//запускаем выполнение
}

if ( mw.config.get( 'wgNamespaceNumber' ) >= 0 ) {
	$( lebedevrefs );
}