_ _    _ _____  ___   __                       
 __      _(_) | _(_)___ / ( _ ) / /_   ___ ___  _ __ ___  
 \ \ /\ / / | |/ / | |_ \ / _ \| '_ \ / __/ _ \| '_ ` _ \ 
  \ V  V /| |   <| |___) | (_) | (_) | (_| (_) | | | | | |
   \_/\_/ |_|_|\_\_|____/ \___/ \___(_)___\___/|_| |_| |_|

Wikipedysta:Matma Rex/infobox.js

Znaczenie Wikipedysta:Matma Rex/infobox.js w dzisiejszym społeczeństwie jest niezaprzeczalne. Wikipedysta:Matma Rex/infobox.js był przedmiotem zainteresowania i debaty w różnych obszarach, od polityki po kulturę popularną. Jego wpływ na codzienne życie ludzi jest oczywisty i odczuwalny we wszystkich aspektach społeczeństwa. W tym artykule zbadamy dzisiejszą rolę Wikipedysta:Matma Rex/infobox.js, analizując jego znaczenie i rolę, jaką odgrywa we współczesnym życiu. Od jego początków po wpływ na współczesny świat, Wikipedysta:Matma Rex/infobox.js to temat, który zasługuje na całościowe przestudiowanie i zrozumienie.
//Wstawiacz infoboksów v. 1.6vector by ABX i Matma Rex
//Instrukcja użycia, pomoc i dyskusja: ]

//Wersja rozwojowa: ]
// <pre>
if(typeof infobox=='undefined') var infobox={}
else alert('Błąd krytyczny - jeden ze skryptów używa już zmiennej "infobox".')

infobox.infoboxes=

importScript('Wikipedysta:Matma Rex/infoboksy.js')
importStylesheet('Wikipedysta:Matma Rex/infobox.css')

if(typeof dodajOpis=='undefined') //powinna już być taka funkcja, ale gdyby nie...
{
	function dodajOpis(opis)
	{
		var wpS = document.editform.wpSummary;
		if (wpS.value != '' && wpS.value.charAt(wpS.value.length-2) != '/')
		{
			wpS.value += ', ' + opis
		}
		else
		{
			wpS.value += opis
		}
	}
}

function showhide(el) //pokaż/ukryj el; można podać id elementu
{
	if(typeof el=='string') el=document.getElementById(el)
	
	if(el.style.display=='none') el.style.display=''
	else el.style.display='none'
}

function remove(el) //alias, usuwa i zwraca element/false, gdy nie ma; el może być id elementu
{
	if(typeof el=='string') el=document.getElementById(el)
	
	if(!el) return false
	
	// fix the new toolbar bug
	infobox.refreshSection();

	return el.parentNode.removeChild(el)
}

function hl(el,h) //podświetl/anuluj podświetlenie
{
	if(h==undefined) h=true
 
	if(h) el.style.border='3px solid red'
	else el.style.border=''
}

infobox.message=function(txt,id) //wstawia przed wpTextbox1 diva, zwraca referencję
{
	var box = document.getElementById(id);
	if (!box)
		box=document.createElement('div')
	;
	box.innerHTML=txt
	box.id=id
	
	var el = document.getElementById('infoboxSelectorBox');
	if (!el)
		el=document.getElementById('editform')
	;
	el.parentNode.insertBefore(box,el)

	// fix the new toolbar bug
	infobox.refreshSection();
	
	return box
}

infobox.insertSelector=function() //wstawia selectboksa
{
	var txt = ""
	txt += '<form onsubmit="infobox.openInsertingForm(); return false" style="display:inline"><select id="infobox_selector" size="1">';
	txt += '<option selected="selected" value="-1">Wybierz infobox:'
	
	for(ibx=0;ibx<infobox.infoboxes.length;ibx++)
	{
		txt += '<option value="' + ibx + '">' + infobox.infoboxes.selname
	}
 
	txt += '</select> <input id="wpInfobox" type="submit" value="Wypełnij" accesskey="i" title="Rozpocznij wypełnianie infoboksu"></form> <input type="button" value="Wczytaj infobox z artykułu" onclick="infobox.loadFromArticle()" /> '
	
	
	txtexpanded='<span style="display:none" id="infobox_txtexpanded"><input type="button" value="Wczytaj infobox z kodu" onclick="infobox.spawnInsertCodeBox()" /> <input type="button" value="Pobierz wywołanie infoboksu" onclick="z=prompt(\'Podaj nazwę infoboksu (wraz z \\\'infobox\\\' na końcu):\');if(typeof z!=\'undefined\'){infobox.loadCodeFromTemplateName(z)}" /> <input type="button" value="&laquo;" onclick="showhide(\'infobox_txtexpanded\');showhide(\'infobox_txtnonexp\')" /></span>'
	
	txtnonexp='<span id="infobox_txtnonexp"><input type="button" value="&raquo;" onclick="showhide(\'infobox_txtexpanded\');showhide(\'infobox_txtnonexp\')" /></span>'
	
	
	txt+=txtnonexp+txtexpanded
	
	infobox.message(txt,'infoboxSelectorBox')
}

infobox.findInText=function(text) //znajduje infoboksy w wikitekście; opis zwracanych wartości pod koniec funkcji
{
	arr= //przechowuje znalezione infoboksy
	
	//regexp na znajdowanie infoboksów - dzięki, Nux
	text.replace(/\{\{(+ infobo+)({40,}|(?:\s|\|*|\|*=(?:*|(?:*(?:\{\{+\}\}|\]+\]\])*)+))+)\}\}/g, function(a,n,z)
	{
		arr.push('{{'+n+z+'}}') //wrzucamy infoboks do tablicy
	})
	
	//zwracane wartości:
	// 0 - nic nie znaleziono
	// string - kod infoboksu
	// array - tablica z kodami infoboksów, gdy są dwa lub więcej
	
	if(arr.length==0) return 0
	else if(arr.length==1) return arr
	else return arr
}

infobox.loadFromArticle=function()
{
	ib=infobox.findInText(document.getElementById('wpTextbox1').value)
	
	if(ib==0) alert('W kodzie artykułu nie znaleziono żadnych infoboksów. Jeśli jesteś pewien, że jakieś są, spróbuj użyć funkcji "Wczytaj infobox z kodu" i zgłoś błąd autorom skryptu.')
	else if(typeof ib=='string') infobox.loadTemplateFromCode(ib)
	else
	{
		txt='W kodzie artykułu znaleziono '+ib.length+' infoboksy/ów. Wybierz, który z nich chcesz edytować:'
		
		for(i in ib)
		{
			n=''
			ib.replace(/^\{\{(.+?)\s*\|/,function(a,nazwa)
			{
				nazwa=nazwa.substring(0,1).toUpperCase()+nazwa.substring(1)
				n=nazwa
				return ''
			})
			
			
			txt+='<br /><input type="submit" value="'+n+'" onclick="infobox.loadTemplateFromCode(\''+ib.replace(/\r?\n/g,' ')+'\');remove(this.parentNode)" />'
		}
		
		infobox.message(txt,'')
	}
}

infobox.spawnInsertCodeBox=function()
{
	infobox.hideInsertCodeBox()
	
	infobox.message(
	'Wklej pełny kod infoboksu: <textarea style="width:50px;height:1em;display:inline" id="infoboxCode"></textarea> <input type="submit" value="OK" onclick=\'infobox.loadTemplateFromCode(document.getElementById("infoboxCode").value);infobox.hideInsertCodeBox()\' />',
	'insertInfoboxCodeBox'
	)
	
	document.getElementById('infoboxCode').focus()
}

infobox.hideInsertCodeBox=function()
{
	remove('insertInfoboxCodeBox')
}
 
infobox.openInsertingForm=function() //umożliwia wypełnianie pól
{
	if(document.getElementById('insertingInfoboxForm')) return //tylko jedno na raz
 
	var selector = document.getElementById('infobox_selector')
	if (!selector) return
 
	var n = Number(selector.options.value)
	if(n<0) return //jeśli nic nie wybrano
 
	txt='<form id="insertingInfoboxForm" action="index.php" method="POST" onsubmit="infobox.pasteCode();dodajOpis(\']\');return false">'
 
	txt+='{{<input type="hidden" id="__name" value="'+infobox.infoboxes.name+'" />'+infobox.infoboxes.name+' <input type="submit" value="Wstaw" /> <input type="button" value="Podgląd wypełnienia" onclick="infobox.loadPreview(infobox.createCode())"> <input type="button" value="Podgląd pustego infoboksu" onclick="infobox.loadPreview(\'{{'+infobox.infoboxes.name+'}}\')"> <input type="reset" value="Anuluj" onclick="infobox.closeInsertingForm()" /><br /><div id="insertingInfobox">'

	for(i in infobox.infoboxes.para)
	{
		pname=infobox.infoboxes.para
		pval=infobox.infoboxes.para||''
		pinfo=infobox.infoboxes.para||false
 
		txt+=infobox.parseTemplateLine(pname,pval,pinfo)
	}
 
	txt+='</div>}} <input type="submit" value="Wstaw" /> <input type="reset" value="Anuluj" onclick="infobox.closeInsertingForm()" /></form>'
 
	infobox.message(txt,'insertingInfoboxFormDiv')
}

infobox.closeInsertingForm=function() //ukrywa wypełnianie pól
{
	remove('insertingInfoboxFormDiv')
}

infobox.parseTemplateLine=function(name,val,info) //parsowanie zmiennych <<>>
{
	if(val.indexOf('<<')==-1) //brak specjalnych znaków - jeden zwykły input/textarea
	{
		z=val.match(/\n/g) //jakieś entery?
		if(z==null) box='<input value="'+val+'" size="20" />' //nie - zwykły input
		else //tak - textarea
		{
			box='<textarea cols="20" rows="'+Math.min(z.length,3)+'">'+val+'</textarea>'
			//wysokość max 3 wiersze
		}
		
		txt=
		' | '+name+(info?' <dfn class="info">('+info+')</dfn>':'')+
		' = '+
		'<span id="ibox-'+name+'">'+
		box+
		'</span><br />'
 
		return txt
	}
	else //parsujemy wszystkie <<>>
	{
		arr=
		//tablica, w niej na przemian string, <<>>, string, <<>>, itd.
		//w razie potrzeby (gdy po sobie są dwa <<>>) string jest pusty
		//pierwszy element to zawsze string
		//ostatni to <<>> lub string
 
		//substr to nie to samo co substring!
 
		while(val.indexOf('<<')!=-1) //dopóki jest tu jeszcze jakieś <<>>
		{
			idx=val.indexOf('<<') //pozycja <<
 
			if(idx!=0) //gdy mamy najpierw zwykły string
			{
				arr.push(val.substring(0,idx)) //wrzucamy do tablicy ów string
 
				val=val.substr(idx) //po czym odcinamy do od val
			}
			else
			{
				arr.push('') //a gdy nie, wrzucamy pusty
			}
 
			//teraz index << jest równy 0
 
			idx=val.indexOf('>>') //dokąd wycinamy?
 
			arr.push(val.substring(2,idx)) //wrzucamy do tablicy to, co jest pomiędzy << a >>
 
			val=val.substr(idx+2) //odcinamy <<>> z początku
		}
 
		if(val!='') //jeszcze jakiś string na końcu
		{
			arr.push(val)
			val=''
		}
 
 
 
		txt='' //to będzie to, co jest między = a kolejnym |
		for(i in arr)
		{
			if(i%2==0) //liczba parzysta - string
			{
				txt+=arr //po prostu dopisujemy string
			}
			else //nieparzysta - <<>>
			{
				if(arr.indexOf(':')!=-1) //zawiera domyślną wartość
				{
					idx=arr.indexOf(':')
 
					_name=arr.substring(0,idx)
					_default=arr.substr(idx+1)
				}
				else
				{
					_name=arr
					_default=''
				}
				// _name - nazwa zmiennej
				// _default - wartość domyślna
 
 
				//parametr "alt" to regex, który musi pasować do zawartości pola
				//w przeciwnym razie wstawienie jest anulowane
 
				switch(_name) //parsujemy!
				{
					case 'input': //podstawowy input
						txt+='<input value="'+_default+'" />'
						break
					case 'rok':
						txt+='<input maxlength="4" value="'+_default+'" alt="^{1,4}$" />'
						break
					default:
						txt+='<strong>Błąd! Nieznany typ "'+_name+'"!</strong>'
				}
			}
		}
 
		txt=
		' | '+name+(info?' <dfn class="info">('+info+')</dfn>':'')+
		' = '+
		'<span id="ibox-'+name+'">'+
		txt+
		'</span><br />'
 
		return txt
	}
}

infobox.createCode=function() //generuje i zwraca kod, bez walidacji
{
	form=document.getElementById('insertingInfoboxForm')	
 
	txt='{{'+form.__name.value+"\n"
 
	span=form.getElementsByTagName('span')
	for(i=0;i<span.length;i++)
	{
		if(span.id.indexOf('ibox-')==-1||span.id==undefined)
		{
			alert('Błąd!')
			continue //pomijamy
		}

		txt+=' | '+span.id.replace('ibox-','')+' = '+infobox.getRealNodeValue(span)+"\n"
	}

	txt+='}}'

	return txt
}

infobox.pasteCode=function() //generuje kod, waliduje i wstawia do wpTextbox1
{
	form=document.getElementById('insertingInfoboxForm')
	ipts=document.getElementById('insertingInfobox').getElementsByTagName('input')
	for(z=0;z<ipts.length;z++) hl(ipts,false) //wyłącz podświetlenie wszystkich inputów
 
	txt='{{'+form.__name.value+"\n"
 
	span=form.getElementsByTagName('span')
	errors=0
 
	for(i=0;i<span.length;i++)
	{
		if(span.id.indexOf('ibox-')==-1||span.id==undefined)
		{
			alert('Błąd!')
			continue //pomijamy
		}
 
		for(j=0;j<ipts.length;j++)
		{
			if(!ipts.alt) ipts.alt='' //sprawdzamy pole walidacji

			regex=new RegExp(ipts.alt) //robimy z niego regexa

			if(ipts.value.search(regex)==-1 && ipts.value.replace(/^\s+|\s+$/g,'')!='') //po czym sprawdzamy, czy regex pasuje lub czy pole jest puste
			{
				hl(ipts)
				errors++ //i w razie potrzeby wywalamy error
			}
		}

		txt+=' | '+span.id.replace('ibox-','')+' = '+infobox.getRealNodeValue(span)+"\n"
	}

	if(errors>0)
	{
		alert('W formularzu pojawiły się błędy ('+errors+')! Odpowiednie pola zostały podświetlone, popraw je i kliknij "Wstaw" ponownie.')
		return
	}

	txt+='}}'+"\n"

	document.getElementById('wpTextbox1').value=txt+document.getElementById('wpTextbox1').value
		

	remove(form.parentNode)
}
 
infobox.getRealNodeValue=function(el) //pobiera ciągi tekstowe + wartości inputów w elemencie
{
	val=''
	for(z=0;z<el.childNodes.length;z++)
	{
		if(el.childNodes.nodeType==3) //string
		{
			val+=el.childNodes.nodeValue
		}
		else //nie string - element HTML, zapewne input/textarea
		{
			if(el.childNodes.value) val+=el.childNodes.value
		}
	}
 
	return val
}

infobox.loadTemplateFromCode=function(code,options) //generuje wypełnianie na podstawie wywołania, wczytuje także wartości
{
	if(typeof options=='undefined') options={}
	
	code=code.replace(/^\s*/g,'').replace(/\s*$/g,'') //trim
	
	if(code.indexOf('{{')!=0 || code.lastIndexOf('}}')!=(code.length-2) || code.indexOf('|')==-1)
	{
		alert('Kod musi zawierać tylko infobox - zaczynający się od {{, kończący }} i zawierający co najmniej jedno |.')
		return false
	}
	
	newInfobox={}

	code=code.replace(/^\{\{(.+?)\s*\|/,function(a,nazwa)
	{
		nazwa=nazwa.substring(0,1).toUpperCase()+nazwa.substring(1)
		newInfobox.name=nazwa
		
		if(typeof options.forceSelname=='undefined') newInfobox.selname=nazwa+', wczytany z kodu'
		else newInfobox.selname=options.forceSelname.replace('{nazwa}',nazwa)
		return ''
	})
	code=code.replace(/\s*\}\}$/,'')
	
	
	// escapowanie parametrów - autor kodu: Nux
	
	// wewnętrzne szablony
	code = code.replace(/<<<(#+)>>>/g,'<<<#$1>>>').replace(/\{\{+\}\}/g,function(a){ return a.replace(/\|/g,'<<<#>>>') })
	// wewnętrzne linki
	code = code.replace(/\]+\]\]/g,function(a){ return a.replace(/\|/g,'<<<#>>>') })
	
	
 
	lines=code.split('|')
	newInfobox.para=
 
	for(i=0;i<lines.length;i++)
	{
		line=lines
		// odescapowanie parametrów - autor kodu: Nux
		line=line.replace(/<<<#>>>/g,'|').replace(/<<<#(#+)>>>/g,'<<<$1>>>')
		
		line=line.replace(/^\s*(.+?)\s*=\s*(*?)\s*$/,function(str,p1,p2)
		{
			p3=''
			p2=p2.replace(/(\s*)<!--(+)-->(\s*)/,function(a,s1,info,s2)
			{
				if(s1+s2=='') rv=''
				else rv=' '
				
				p3=info.replace(/^\s*/g,'').replace(/\s*$/g,'') //trim
				
				return rv
			})
			
			newInfobox.para.push()
 
			return ''
		})
		if(line!='') alert('Błędny parametr infoboksu:'+"\n"+line)
	}
	
	infobox.infoboxes=newInfobox //gotowe - dołączamy do listy
	
	//odświeżamy selectboksa
	//remove('infoboxSelectorBox')
	infobox.insertSelector()
	
	sel=document.getElementById('infobox_selector')
	sel.selectedIndex=sel.options.length-1 //zaznacz ostatnie
	infobox.openInsertingForm() //pokaż pole wypełniania
}

infobox.callApi=function(query) //z biblioteki Beau
{
	var url = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?';
	
	for (var field in query)
	{
		var value = query;
		url += '&' + field + '=' + encodeURIComponent(value);
	}
	
	url += '&format=json';
	
	mw.loader.load(url);
}

infobox.loadCodeFromTemplateName=function(name) //na podstawie http://pl.wikipedia.orghttps://wiki386.com/pl/Wikipedysta:Beau/infobox.js - dzięki, Beau
{
	infobox.callApi(
	{
		action:	'query',
		prop:	'revisions',
		titles:	'Szablon:' + name + "|Szablon:" + name + "/opis|Dyskusja szablonu:" + name,
		rvprop:	'content',
		callback:	'infobox.parseInstructionQuery'
	}
	)
}

infobox.parseInstructionQuery=function(response) //na podstawie http://pl.wikipedia.orghttps://wiki386.com/pl/Wikipedysta:Beau/infobox.js - dzięki, Beau
{
	var instr;
	for (var page_id in response.query.pages)
	{
		var page = response.query.pages;
		if (!page.revisions) continue;
		
		var rvcontent = page.revisions;

		var found = rvcontent.match(/<pre>\s*?(\{\{(?:.|\s)+?)<\/pre>/im);
		if (found)
		{
			instr = found
			break
		}
	}

	if (!instr)
	{
		alert("Nie udało się znaleźć wywołania. Upomnij się o nie na wikiprojekcie: ]. Jeśli jesteś pewien, że wywołanie jest, a skrypt go nie znalazł, zgłoś błąd autorom.");
		return;
	}
	
	ib=infobox.findInText(instr)
	if(typeof ib=='string') infobox.loadTemplateFromCode(ib,{forceSelname:'{nazwa}, wywołanie pobrane automatycznie'})
}

infobox.loadPreview=function(infoboxCode)
{
	infobox.callApi(
	{
		action:'parse',
		text:infoboxCode,
		callback:'infobox.showPreview'
	}
	)
}

infobox.showPreview=function(response)
{
	text=response.parse.text
	
	infobox.message('<input type="submit" value="Zamknij podgląd" onclick="remove(\'infoboxPreview\')" />'+text+'<div style="clear:both">&nbsp;</div>','infoboxPreview')
}

if(mw.config.get('wgAction')=='edit' || mw.config.get('wgAction')=='submit') addOnloadHook(infobox.insertSelector)

// ----------------------------------------------------
// Move whole toolbar to a section of the New Toolbar
//
infobox.moveToNew = function()
{
	var nbar = document.getElementById('wikiEditor-ui-toolbar');
	if (!nbar)
	{
		return;
	}
	$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
		'sections': {
			'mrinfoboksy': {
				'type': 'toolbar',
				'label': (mw.config.get('wgUserLanguage')=='pl' ? "Infoboksy" : "Infoboxes")
			}
		}
	} );
 
	infobox.elBoxSec = getElementsByClassName(nbar, "div", "section-mrinfoboksy");
	// move toolbar to proper place
	var el = document.getElementById('infoboxSelectorBox');
	infobox.elBoxSec.appendChild(el);
	// fix the new toolbar bug
	infobox.refreshSection();
}
// fix the new toolbar bug
infobox.refreshSection = function()
{
	if (infobox.elBoxSec)
	{
		setTimeout(function()
		{
			if (infobox.elBoxSec.clientHeight>2)
			{
				infobox.elBoxSec.parentNode.style.height = (infobox.elBoxSec.clientHeight+1) + 'px';
			}
		}, 100);
	}
}
// </pre>