MediaWiki:Gadget-AdvancedContribs.js

Nòta : Aprèp aver publicat la pagina, vos cal forçar son recargament complet tot ignorant lo contengut actual de l'amagatal de vòstre navigador per veire los cambiaments : Mozilla / Firefox / Konqueror / Safari : mantenètz la tòca Majuscula (Shift) en clicant lo boton Actualizar (Reload,) o quichatz Maj-Ctrl-R (Maj-Cmd-R sus Apple Mac) ; Internet Explorer / Opera : mantenètz la tòca Ctrl en clicant lo boton Actualizar o quichatz Ctrl-F5.

if(mw.config.get('wgUserGroups').indexOf("sysop") != -1) 
{
	var ACobj = {}
	
	ACobj.FollowState = false //l'estat dels ligams users (cap a la pagina o cap al javascript)

	loadJsForced("User:" + mw.config.get('wgUserName') + "/AdvancedContribs.js")

	//apondre l'onglet seguit dels users
	if(mw.config.get('wgNamespaceNumber')!=0 || mw.config.get('wgAction') == "history") 
		$(function ()
		{
			var list = document.getElementById('p-cactions')
		
			AC_initVarsMin()
		
			if(!list) return
			list = list.childNodes[3].childNodes[1]
		
			var elt = document.createElement('li')
			var a = document.createElement('a')
			
			a.onclick = toggleFollowAnchor
			a.href = "#"
			a.id = "caa_userFollow"
			a.appendChild(document.createTextNode("Seguit dels users"));
			elt.appendChild(a)
			list.appendChild(elt)
			
			if(AC_changeFollowListLink)
			{
				var li = document.getElementById("pt-watchlist")
				if(li) li.firstChild.href = "/wiki/Utilizaire:Cedric31/AdvancedContribs"
			}
		})
	
	//se òm es dins la sospagina user/AdvancedContrib, alara s'avia lo bozin	
	if (mw.config.get('wgTitle') == "Cedric31/AdvancedContribs" && mw.config.get('wgAction') == "view")
	{	
		//se declara las variablas pas que se son utilas
		ACobj.USERCONTRIBLIMIT = 0 //tipe per addWarning()
		ACobj.WATCHLISTLIMIT = 1 //tipe per addWarning()
		ACobj.HISTORYLIMIT = 2 //tipe per addWarning()
		ACobj.CHANGEVERSION = 3 //tipe per addWarning()
		ACobj.INITTITLE = 4
		
		/*
		ACobj.CellWithAnchor //una cellula e un anchor a l'interior, per la duplicacion
		ACobj.DateRegExp  //la regexp per las datas
		ACobj.ArticlesWrotten //l'objècte que conten totes los articles ja marcats
		ACobj.timeStampLimit //la data a partir de laquala se trapa los istorics en timeStamp
		ACobj.dateLimit //la data a partir de laquala se trapa los istorics
		
		ACobj.requestStack //per blocar las accions quand las requests son aviadas
		*/
		//las variablas localas son lai per poder cargar la pagina sens salvar los paramètres
		/*
		ACobj.delayContrib_LOC
		ACobj.includeFollowList_LOC
		ACobj.version_LOC //n° de version en cors, mesa sus la pagina de AC
		*/
		ACobj.version = "0.9.24"  //n° de version de l'escript
		
		$(function ()
		{
			var div=document.getElementById('bodyContent')
			
			var getAnchorsFollowed = function()
			{
				var res = ""
				
				for(var i=0;i!=AC_BlackList.length;i++)
					res = res + htmlUserPageLink(AC_BlackList[i]) + " "
					
				return res
			}
			
			AC_initVars()
			
			ACobj.version_LOC = getVersionNo(div.textContent)
			ACobj.delayContrib_LOC = AC_delayContrib
			ACobj.includeFollowList_LOC = AC_includeFollowList
			
			div.innerHTML= "<style>.trover{} " +
						".trover:hover{background:#e5e5e5} </style>" +
						"<table><tr><td>Montar las contributions <select id='AC_delayContrib'>" + 
						"<option value='1' " + iif(AC_delayContrib==1, "SELECTED","") + ">de la darrièra ora</option>" + 
						"<option value='3' " + iif(AC_delayContrib==3, "SELECTED","") + ">de las 3 darrièras oras</option>" + 
						"<option value='6' " + iif(AC_delayContrib==6, "SELECTED","") + ">de las 6 darrièras oras</option>" + 
						"<option value='12' " + iif(AC_delayContrib==12, "SELECTED","") + ">de las 12 darrièras oras</option>" + 
						"<option value='18' " + iif(AC_delayContrib==18, "SELECTED","") + ">de las 18 darrièras oras</option>" + 
						"<option value='24' " + iif(AC_delayContrib==24, "SELECTED","") + ">del darrièr jorn</option>" + 
						"<option value='48' " + iif(AC_delayContrib==48, "SELECTED","") + ">dels dos darrièrs jorns</option>" + 
						"<option value='72' " + iif(AC_delayContrib==72, "SELECTED","") + ">dels tres darrièrs jorns</option>" + 
						"<option value='168' " + iif(AC_delayContrib==168, "SELECTED","") + ">de la setmana passada</option></select></td>" +
						"<input type=checkbox id='AC_includeFollowList' " + iif(AC_includeFollowList,"checked","") + ">" + 
						"<label for='AC_includeFollowList'>Enclure la lista de seguit</label>" + 
						"<td><button id='btn_reload' onclick='setLocalParameters()'>Tornar cargar amb aquestes paramètres</button></td>" + 
						"<td><button id='btn_save' onclick='saveParameters()'>Enregistrar aquestes paramètres</button></td>" + 
						"</tr></table>" +
						"<small><div id='contribContent'>&nbsp;</div>" + 
						"<div id='WarningDiv' style='display:none;border:2px solid #FF9900;padding-left:3px'><b><big>Warnings</big></b><br></div>" + 
						"<div id='AlertDiv' style='display:none;border:2px solid #FF0000;padding-left:3px'><b><big>Alerts</big></b><br></div>" + 
						"<center><div>" + getAnchorsFollowed() + "</div>" +
						"<div>" + 
						"<a href='/wiki/Utilizaire:Maloq/AdvancedContribs/Todo' title='todo'>ToDo</a> - " +
						"<a href='/wiki/Utilizaire:Maloq/AdvancedContribs/Documentacion' title='Documentacion'>Documentacion</a> - " +
						"<a href='/wiki/Utilizaire:" + mw.config.get('wgUserName') + "/AdvancedContribs.js' title='Vòstres paramètres'>Vòstres paramètres</a>"  +
						"</div></center></small>"
		
				
			//se crea la regexp pel timestamp
			ACobj.DateRegExp = new RegExp();
			ACobj.DateRegExp.compile(/^(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)Z$/)
				
			//aquesta cellula es la cellula de basa que conten un sol anchor
			ACobj.CellWithAnchor = document.createElement("td")
			ACobj.CellWithAnchor.appendChild(document.createElement("a"))
			ACobj.CellWithAnchor.style.paddingRight='3px'
			ACobj.CellWithAnchor.style.width='0%'
			
			getData()
		});
		
	}
}

	//inicializa las variablas necessària a l'onglet sens aver la lista: optimizar lo temps
	function AC_initVarsMin()
	{
		try {if(AC_changeFollowListLink){}}
		catch(e){ AC_changeFollowListLink = false }
	}
	
	
	//inicializa las variablas per la pagina de contrib, s'existisson pas, la foncion las crea
	function AC_initVars()
	{	
		try	{if(AC_BlackList){}}
		catch(e){ AC_BlackList = new Array() }
		
		try {if(AC_WhiteList){}}
		catch(e){ AC_WhiteList = new Array() } 
		
		try {if(AC_debugFlag){}}
		catch(e){ AC_debugFlag = false }
		
		try {if(AC_delayContrib){}}
		catch(e){ AC_delayContrib = 24 }
		
		try {if(AC_includeFollowList){}}
		catch(e){ AC_includeFollowList = false }
		
		try {if(AC_watchListLimit){}}
		catch(e){ AC_watchListLimit = 5000 }
		
		try {if(AC_historyLimit){}}
		catch(e){ AC_historyLimit = 500 }
		
		try {if(AC_userContribLimit){}}
		catch(e){ AC_userContribLimit = 500 } 
		
		try {if(AC_blackListColor){}}
		catch(e){ AC_blackListColor = '#FFB0B0' } 
		
		try {if(AC_whiteListColor){}}
		catch(e){ AC_whiteListColor = '#B0B0FF' }
		
		try {if(AC_normalListColor){}}
		catch(e){ AC_normalListColor = '#B0FFB0' }
		
		try {if(AC_displayDeleteLink){}}
		catch(e){ AC_displayDeleteLink = false }
		
		try {if(AC_displayWarnings){}}
		catch(e){ AC_displayWarnings = true }
		
		try {if(AC_changeFollowListLink){}}
		catch(e){ AC_changeFollowListLink = false }
	}
	
	
	/////////////////////////////////////TOOLBOX  ///////////////////////////////////////////////////
	
	//if en fonction
	function iif(cond, ifTrue, ifFalse)
	{
		if(cond) return ifTrue
		
		return ifFalse
	}
	
	//charge un js en forçant la purge du cache
	function loadJsForced(page) 
	{
		var date = new Date().getTime()
		mw.loader.load('//fr.wikipedia.org/w/index.php?title=' + encodeURIComponent(page) +
		'&action=raw&ctype=text/javascript&dummy=' + date);
	}
	
	//renvia la string comentària parsada per aver los ligams
	function wikiParse(string)
	{
		string = string.replace(/&/, '&amp;');
		string = string.replace(/>/, '&gt;');
		string = string.replace(/</, '&lt;');
		string = string.replace(/"/, '&quot;');
		
		//los [[ligams]]
		string = string.replace(/\[\[(([^\]\|]*)(.*?))\]\]/g, '<a href="'+mw.config.get('wgServer')+wgScriptPath+'/index.php?title=$2&redirect=no" >$1</a>');
		string = string.replace(/\>[^\]\|<]*\|([^\]\|<]*)</g, ">$1<");
		
		//los comentaris
		string = string.replace(/\/\*([^\*\/]*)\*\//g, "<span style='color:#888888'>/*$1*/</span>");
		
		//los {{a|article}}
		string = string.replace(/\{\{a\|([^\}]*)\}\}/g, '<a href="'+mw.config.get('wgServer')+wgScriptPath+'/index.php?title=$1&redirect=no">$1</a>');
		
		//los {{u|utilizaire}}
		string = string.replace(/\{\{u\|([^\}]*)\}\}/g, '<a href="'+mw.config.get('wgServer')+wgScriptPath+'/index.php?title=Utilisateur:$1">$1</a>');
		
		return string 
	}
	
	//parse la cadena de caratèr e la transfòrma en data
	function parseDate(string)
	{
		var now = new Date();
		var match = ACobj.DateRegExp.exec(string);
		
		if (!match) return now
		
		now.setFullYear(match[1],(match[2])-1, match[3])
		now.setHours(match[4], match[5], match[6],0)
		
		now.setTime(now.getTime() + (-now.getTimezoneOffset())*60*1000)
		
		return now
	}
	
	/////////////////////////////////////FONCIONS LIGADAS A L'ONGLET//////////////////////////////////
	
	
	//cambia l estat de l'user (0: res, 1 seguit, 2 fisança)
	function toggleUserAction(user, action)
	{
		var BLPos = AC_BlackList.indexOf(user)
		var WLPos = AC_WhiteList.indexOf(user)
		var Summeray
	
		if(action == 1 && BLPos==-1)
		{
			AC_BlackList[AC_BlackList.length] = user
			if(WLPos!=-1) AC_WhiteList.splice(WLPos, 1)
			
			ajaxSetUsersPage('Apond ' + user + ' dins la lista de susvelhança',user, AC_blackListColor)
		}
		else if(action == 2 && WLPos==-1)
		{
			AC_WhiteList[AC_WhiteList.length] = user
			if(BLPos!=-1) AC_BlackList.splice(BLPos, 1)
			
			ajaxSetUsersPage('Apond ' + user + ' dins la lista de fisança',user, AC_whiteListColor)
		}	
		else if(action == 0 && (WLPos!=-1 || BLPos!=-1))
		{
			if(BLPos!=-1) AC_BlackList.splice(BLPos, 1)
			if(WLPos!=-1) AC_WhiteList.splice(WLPos, 1)
			
			ajaxSetUsersPage('suprimís ' + user + ' de las doas listas',user, AC_normalListColor)
		}
		
		document.AC_infoBox.style.display="none"
	}
	
	
	//aficha la pichona boita de dialòg
	function toggleUser(e)
	{
		var user = this.AC_user
		
		var AC_infoBox = document.AC_infoBox
		
		if(!AC_infoBox)
		{
			AC_infoBox = document.createElement("div")
			AC_infoBox.style.border="1px solid grey"
			AC_infoBox.style.background="#FFFFFF"
			
			AC_infoBox.style.zIndex = "2"
			AC_infoBox.style.position = "absolute"
			
			
			var labels = ['Cap de lista','Lista de susvelhança','Lista de fisança']
			for(var i=0; i!=labels.length;i++)
			{
				var input = document.createElement("input")
				var label = document.createElement("label")
				label.htmlFor='AC_infoboxCheck' + i
				label.textContent = labels[i]
				label.style.cursor="puntar"
				label.marginBottom='2px'
				input.name = "AC_infobox"
				input.id='AC_infoboxCheck' + i
				input.type='radio'
				input.style.width = '12px'
				input.action=i
				
				AC_infoBox.appendChild(input)
				AC_infoBox.appendChild(label)
				AC_infoBox.appendChild(document.createElement('br'))
				
				input.onclick = function()
				{
					if(!this.checked) return
					toggleUserAction(document.AC_infoBox.user, this.action)
				}
				
				AC_infoBox["input"+i] = input
			}
		
			document.body.appendChild(AC_infoBox)
			document.AC_infoBox = AC_infoBox
		}
		else if(AC_infoBox.style.display=="")
		{
			AC_infoBox.style.display="none"
			if(user==AC_infoBox.user)	return
		}
		
		
		AC_infoBox["input"+0].checked = true
		
		var inBlackList = AC_BlackList.indexOf(user) != -1
		var inWhiteList = AC_WhiteList.indexOf(user) != -1
			
		if(inBlackList) AC_infoBox["input"+1].checked = true
		else if(inWhiteList) AC_infoBox["input"+2].checked = true
			
		
		
		var posx = 300;
		var posy = 300;
		
		if (e.pageX) 	
		{
			posx = e.pageX;
			posy = e.pageY;
		}
		else if (e.clientX ) 	
		{
			posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
			posy = e.clientY + document.body.scrollTop	+ document.documentElement.scrollTop;
		}
		
		AC_infoBox.style.top = (posy + 15) +  "px"
		AC_infoBox.style.left = posx + "px"
		
		AC_infoBox.user = user						
		AC_infoBox.style.display=""	
	}
	
	//càmbia l'estat dels anchors associat a user (FollowedColor: color de metre)
	function setAnchorState(user, FollowedColor) 
	{
		var i
		var len = ACobj.UsersAnchors[user].length
		
		for(i=0;i!=len;i++)
			ACobj.UsersAnchors[user][i].style.background = FollowedColor
	
	}
	
	//lupin :p
	function getUserFromHref(href)
	{
		var regexp = new RegExp(/(\/wiki\/Utilizaire:|\/wiki\/Special:Contributions\/|\/w\/index.php\?title=Utilizaire:|\/wiki\/Discussion_Utilizaire:)([^\/&]+)([&]?.*)$/)
		var match = regexp.exec(href)
		
		if(match) return decodeURIComponent(match[2]).replace(/_/g, " ")
		
		return ""
	}
	
	//function que cèrca los anchor cap a las paginas users e que càmbia lo href (siá cap a la foncion js, siá cap a la pagina user)
	function toggleFollowAnchor() 
	{
	
		var localAnchors
		var i, user, len
		var first = false
	
		AC_initVars()
	
		if(!ACobj.Anchors)
		{
			first = true
			ACobj.UsersAnchors = new Object()
			ACobj.Anchors = new Array()
			localAnchors = document.getElementById('bodyContent').getElementsByTagName('a')
		}
		else
		{
			localAnchors = ACobj.Anchors
		}
	
		len = localAnchors.length
	
		if(ACobj.FollowState == false)
		{
			if(first) //se dedobla lo for per que siá mai rapid
			{
				for(i=0;i!=len;i++)
				{
					user = getUserFromHref(localAnchors[i].href)
	
					if(user!="")
					{
						if(!ACobj.UsersAnchors[user]) ACobj.UsersAnchors[user] = new Array()
						ACobj.UsersAnchors[user][ACobj.UsersAnchors[user].length] = localAnchors[i]
						ACobj.Anchors[ACobj.Anchors.length] = localAnchors[i]
	
						localAnchors[i].AC_user = user
						localAnchors[i].AC_hrefSave = localAnchors[i].href
						localAnchors[i].href = '#'
						
						localAnchors[i].onclick =toggleUser
						
						if(AC_BlackList.indexOf(user)!=-1 ) localAnchors[i].style.background = AC_blackListColor
						else if(AC_WhiteList.indexOf(user)!=-1 ) localAnchors[i].style.background = AC_whiteListColor
						else localAnchors[i].style.background = AC_normalListColor
					}
				}  
			}
			else
			{
				for(i=0;i!=len;i++)
				{
					user = localAnchors[i].AC_user
					localAnchors[i].href = '#'
					localAnchors[i].onclick =toggleUser
					
					if(AC_BlackList.indexOf(user)!=-1 ) localAnchors[i].style.background = AC_blackListColor
					else if(AC_WhiteList.indexOf(user)!=-1 ) localAnchors[i].style.background = AC_whiteListColor
					else localAnchors[i].style.background = AC_normalListColor
	
				}
			}
	
			document.getElementById('caa_userFollow').textContent='Liens users normaux'
	
			ACobj.FollowState = true
		}
		else
		{
			//la, lo primièr passatge ja a emplenat los tablèus
			for(i=0;i!=len;i++)
			{	
				localAnchors[i].href = localAnchors[i].AC_hrefSave
				localAnchors[i].style.background=''
			}
			document.getElementById('caa_userFollow').textContent='Seguit dels users'
	
			ACobj.FollowState = false
		}
	}
	
	////////////////////////////////////////FONCIONS LIGADAS A LA LISTA, O A LAS DOAS
	
	//cèrca lo numèro de version dins lo textContent de bodyContent
	function getVersionNo(str)
	{
		var regexp = new RegExp()
		var match
		
		
		regexp.compile(/§§§([^#]*)§§§/)
		match = regexp.exec(str)
		
		if(match) return match[1]
		
		return ""
	}
	
	
	
	//linha de debug
	function addAlert(Text)
	{
		if(AC_debugFlag)
		{
			var div = document.getElementById('AlertDiv')
			
			if(!div)
				alert(Text)
			else
			{
				var newDiv = document.createElement('div')
				div.style.display=''
				newDiv.innerHTML = Text 
				div.appendChild(newDiv)
			}
		}
	}
	
	//aficha los warnings
	function addWarning(Type, Data1)
	{
		var div = document.getElementById('WarningDiv')
		var newDiv = document.createElement('div')
		var str
		
		if(AC_displayWarnings) div.style.display=''
		
		switch(Type)
		{
			case (ACobj.USERCONTRIBLIMIT):
			{
				str = "Lo limit de requèsta (" + AC_userContribLimit + ") es estat atench per las contribucions de " + htmlUserLink(Data1)
				break
			}
			case (ACobj.WATCHLISTLIMIT):
			{
				str = "Lo limit de requèsta (" + AC_watchListLimit + ")  es estat atench per vòstra <a href='/wiki/Special:Watchlist'>lista de seguit</a>"
				break
			}
			case (ACobj.HISTORYLIMIT):
			{
				str = "Lo limit de requèsta (" + AC_historyLimit + ")  es estat atench per l'istoric de " + htmlArticleLink(Data1)
				break
			}
			case (ACobj.CAMBIAVERSION):
			{
				str = "<big>Una version novèla d'<b>AdvancedContribs</b> es sortida, tornatz cargar vòstre amagatal.</big>"
				break
			}
			case (ACobj.INITTITLE):
			{
				str = "<big><b>Warnings</b></big>"
				div.innerHTML = ''
				div.style.display='none'
				break
			}
		}
		
		newDiv.innerHTML = str
		
		div.appendChild(newDiv)
	}
	
	//met las valors del formulari dins las variablas localas e tòrna cargar
	function setLocalParameters()
	{
		ACobj.delayContrib_LOC = document.getElementById('AC_delayContrib').value
		ACobj.includeFollowList_LOC = document.getElementById('AC_includeFollowList').checked
		
		getData()
	}
	
	
	//met las valors del formulari dins las variablas, salva e tòrna cargar la pagina
	function saveParameters()
	{
		AC_delayContrib = document.getElementById('AC_delayContrib').value
		AC_includeFollowList = document.getElementById('AC_includeFollowList').checked
		
		ajaxSetUsersPage("Modifica los paramètres")	
	}
	
	
	
	//renvia una cadena de caractèrs en metent de zèros a las plaças voidas, maximum 4 la talha
	function toNString(num, length)
	{
		num = num + ""
		
		while(num.length < length)
			num = "0" + num
			
		return num
	}
	
	//renvia lo timeStamp dempuèi l'objècte data
	function getTimeStamp(date)
	{
		return date.getFullYear() + "-" +
				toNString(date.getMonth() + 1, 2) + "-" +
				toNString(date.getDate(), 2) + "T" +
				toNString(date.getHours(), 2) + ":" +
				toNString(date.getMinutes(), 2) + ":" +
				toNString(date.getSeconds(), 2) + "Z"
	}
	
	
	//crae las variables en Js pel salvament
	function getVariablesStrForSaving()
	{
		var res = "var AC_BlackList = new Array("
		var i
		
		for(i=0;i!=AC_BlackList.length;i++)
		{
			if(i!=0) 	res = res + ","
			res = res + "'" + AC_BlackList[i].replace(/'/,"\\'") + "'"
		}
		
		res = res + "); //lista dels users seguits\n" +
		"var AC_WhiteList = new Array("
		
		for(i=0;i!=AC_WhiteList.length;i++)
		{
			if(i!=0) 	res = res + ","
			res = res + "'" + AC_WhiteList[i].replace(/'/,"\\'") + "'"
		}
		
		
		return res + "); //lista dels users de fisança\n" +
		"var AC_debugFlag=" + AC_debugFlag + "; //infos de debogatge (daissar a fals)\n" +
		"var AC_delayContrib=" + AC_delayContrib + "; //en ora, fins a quand se va quérer las contribs\n" +
		"var AC_includeFollowList=" + AC_includeFollowList + "; //se s'inclutz los articles de la lista de seguit\n" +
		
		"var AC_watchListLimit=" + AC_watchListLimit + "; //limit de responsa de la requèsta de la lista de seguit\n" +
		"var AC_historyLimit =" + AC_historyLimit  + "; //limit de responsa de la requèsta de l'istoric d'un article\n" +
		"var AC_userContribLimit=" + AC_userContribLimit + "; //limit de responsa de la requèsta de las contribucions d'un user\n" +
		"var AC_changeFollowListLink=" + AC_changeFollowListLink + "; //se true, càmbia lo ligam 'lista de seguit' cap a la pagina advancedContrib\n" +
		
		"var AC_blackListColor='" + AC_blackListColor + "'; //la color de fons d'un utilizaire seguit en blacklist\n" +
		"var AC_whiteListColor='" + AC_whiteListColor + "'; //la color de fons d'un utilizaire de la whitelist\n" +
		"var AC_normalListColor='" + AC_normalListColor + "'; //la color de fons d'un utilizaire pas seguit\n" +
		
		"var AC_displayDeleteLink=" + AC_displayDeleteLink + "; //aficha un ligam delete per cada article dins la lista (landry-mode)\n" +
	
		"var AC_displayWarnings=" + AC_displayWarnings + "; //aficha los warnings (sovent qd los limits son atenches)\n" 
	}
	
	//a partir de la font d'una pagina html, cèrca la valor de l'input
	//todo: ensajar lo DOMParser
	function getInputValueFromStr(str)
	{
		var regexp = new RegExp()
		var match
		regexp.compile(/value=["']([^"']+)["']/)
		
		match = regexp.exec(str)
		if(match) return match[1]
		
		return ""
	}
	
	//càmbia la pagina user/AdvancedContrib segon lo tablèu Users
	function ajaxSetUsersPage(Summeray, user, color)
	{
		var req=new XMLHttpRequest()
		
		req.onreadystatechange = function()
		{
			if(req.readyState == 4)
			{
				if(req.status==200)
				{			
					var regexp = new RegExp()
					var match
					var wpStarttime = ""
					var wpEdittime = "" 
					var wpEditToken = ""
					var wpWatchthis = ""
					
					regexp.compile(/(<input[^>]+name="wpStarttime"[^>]+>)/)
					match=regexp.exec(req.responseText)
					if(match) wpStarttime = getInputValueFromStr(match[1])
					
					regexp.compile(/(<input[^>]+name="wpEdittime"[^>]+>)/)
					match=regexp.exec(req.responseText)
					if(match) wpEdittime = getInputValueFromStr(match[1])
					
					regexp.compile(/(<input[^>]+name="wpEditToken"[^>]+>)/)
					match=regexp.exec(req.responseText)
					if(match) wpEditToken = getInputValueFromStr(match[1])
					
					regexp.compile(/(<input[^>]+name="wpWatchthis"[^>]+>)/)
					match=regexp.exec(req.responseText)
					if(match) wpWatchthis = getInputValueFromStr(match[1])
					
					var varStr = getVariablesStrForSaving()
					var reqSubmit=new XMLHttpRequest()
					
					var post = "wpTextbox1=" + encodeURIComponent(varStr) + "&wpSummary=" + encodeURIComponent(Summeray)
					post = post + "&wpStarttime=" + encodeURIComponent(wpStarttime)
					post = post + "&wpEdittime=" + encodeURIComponent(wpEdittime)
					post = post + "&wpEditToken=" + encodeURIComponent(wpEditToken)
					post = post + "&wpWatchthis=" + encodeURIComponent(wpWatchthis)
					
					reqSubmit.open("POST","/w/index.php?title=Utilizaire:" + encodeURIComponent(mw.config.get('wgUserName'))  + "/AdvancedContribs.js&action=submit", false)
						
					reqSubmit.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
					reqSubmit.send(post)
					if(user && color) setAnchorState(user, color)
				}
			}
		}
		
		req.open("GET","/w/index.php?title=Utilizaire:" + encodeURIComponent(mw.config.get('wgUserName'))  + "/AdvancedContribs.js&action=edit")
		req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
		req.send(null)
	}
	
	
	//renvia true se l'user es una ip
	function isIP(user)
	{
		var match = user.split(".")
		var i
		
		if(match.length != 4) return false
		
		for(i=0;i!=4;i++)
		{
			match[i] = parseInt(match[i])
			if(isNaN(match[i])) return false
			if(match[i]<0 || match[i]>255) return false
		}
		
		return true
	}
	
	//met la pagina en espèra de la fin dels cargements o la libèra
	//true per dire que fa las requèstas, false per la liberar
	function setPageLocked(state)
	{
	
		document.getElementById('btn_save').disabled =state
		document.getElementById('btn_reload').disabled =state
	
	}
	
	
	//inicializa la pagina per que pòsca recebre las contribs
	function initPage()
	{
		var div = document.getElementById('contribContent')
		var table = document.createElement('table')
		var date = new Date()
		
		addWarning(ACobj.INITTITLE)
		
		if(ACobj.version_LOC != ACobj.version) addWarning(ACobj.CHANGEVERSION)
		
		table.id = 'tablecontrib'
		table.cellPadding = 0
		table.cellSpacing = 0
		
		div.innerHTML = ''
		div.appendChild(table)
		
		//jetlag
		date.setTime(date.getTime() + (date.getTimezoneOffset())*60*1000)
		//on recul de ACobj.delayContrib_LOC jorns
		ACobj.dateLimit = new Date(date.getTime() - ACobj.delayContrib_LOC * 60 * 60 * 1000)
		ACobj.timeStampLimit = getTimeStamp(ACobj.dateLimit)
		
		ACobj.ArticlesWrotten = new Object()
		
		if(ACobj.FollowState == true) toggleFollowAnchor()
		ACobj.FollowState = false 
		ACobj.Anchors = false //per tornar forcer l'estat dels anchors
		
		ACobj.requestStack = 0
		
		setPageLocked(true)
	}
	
	
	//avia las requèstas que van cercar las contribucions dels utilizaires
	function getData()
	{
		var i
	
		initPage()
	
		if(ACobj.includeFollowList_LOC)
			getDataFollowList()
		else //es la lista de seguit qu'apelarç la
			for(i=0;i<AC_BlackList.length;i++)
				getDataUserContrib(AC_BlackList[i])
	}
	
	//fa la requèsta de las contribucions d'aqueste user
	function getDataUserContrib(user)
	{
		var i
		var req=new XMLHttpRequest()
		
		req.user = user
		req.ip = isIP(user)
		req.onreadystatechange = function()
		{
			if(req.readyState == 4)
			{
				if(req.status==200)
				{
					if(!req.responseXML) 
						addAlert("Fracàs al moment de la requèsta de las contribucions de " + req.user)
					else 
					{
						cleanQueryContinue(req.responseXML, ACobj.USERCONTRIBLIMIT, req.user)
						
						if(req.ip) getHistoriesFromIpContrib(req.responseXML, req.user)
						else getHistoriesFromUserContrib(req.responseXML, req.user)
					}
					
					ACobj.requestStack-- 
					if(ACobj.requestStack==0) setPageLocked(false)
				}
			}
		}
		
		if(req.ip)
			req.open("GET","/w/query.php?what=usercontribs&titles=User:" + user + "&uclimit=" + AC_userContribLimit + "&format=xml", true)
		else
			req.open("GET","/w/api.php?action=query&list=usercontribs&ucuser=" + user + "&ucprop=title&uclimit=" + AC_userContribLimit + "&format=xml&ucend=" + ACobj.timeStampLimit, true)
			
		req.setRequestHeader('Content-Type', 'text/xml; charset=utf-8')
		req.send(null)
		ACobj.requestStack++
	}
	
	//fa la requèsta de la lista de seguit
	function getDataFollowList()
	{
		var req=new XMLHttpRequest()
		
		req.onreadystatechange = function()
		{
			if(req.readyState == 4)
			{
				if(req.status==200)
				{
					if(!req.responseXML) addAlert("Fracàs al moment de la requèsta de vòstra lista de seguit")
					else 
					{
						cleanQueryContinue(req.responseXML, ACobj.WATCHLISTLIMIT, "")
						
						writeWatchList(req.responseXML)
	
						for(var i=0;i<AC_BlackList.length;i++) //per poder metre l'async, de met aquò
							getDataUserContrib(AC_BlackList[i])
					}
					
					ACobj.requestStack-- 
					if(ACobj.requestStack==0) setPageLocked(false)
				}
			}
		}
		
		req.open("GeT", "/w/api.php?action=query&generator=watchlist&gwlallrev&prop=revisions&gwllimit=" + AC_watchListLimit + "&format=xml&gwlend=" + ACobj.timeStampLimit, true)
		req.setRequestHeader('Content-Type', 'text/xml; charset=utf-8')
		req.send(null)
		ACobj.requestStack++ 
	}
	
	//neteja las query-continue e aficha los warnings
	function cleanQueryContinue(XmlDoc, alertType, data)
	{
		var nodes = XmlDoc.getElementsByTagName('query-continue')
		
		if(nodes.length!=0)
		{
			var node = nodes[0]
			node.parentNode.removeChild(node)
			addWarning(alertType, data)
		}
	}
			
	
	//cèrca las contribucions d'ip
	function getHistoriesFromIpContrib(XmlDoc, Ip)
	{
		var XmlContribs = XmlDoc.getElementsByTagName('contributions')
		var i, len
		var article
		var date
		
		if(XmlContribs.length==0)
		{
			addAlert("impossible de trobar las contribucions de " + User) 
			return
		}
		
		XmlContribs = XmlContribs[0].childNodes
		
		len = XmlContribs.length
		
		for(i=0; i<len; i++)
		{
			date = parseDate(XmlContribs[i].attributes.timestamp.value)
			article = XmlContribs[i].textContent
			
			if(ACobj.dateLimit.getTime()> date.getTime()) break;
			
			if(ACobj.ArticlesWrotten[article]) continue
			if(article.length == 0) continue
			getArticleHistory(article)
		}
	}
	
	//pren las contribucions d'un utilizaire, e cèrca l'istoric de totes los articles ont a contribuit
	function getHistoriesFromUserContrib(XmlDoc, User)
	{
		var XmlContribs = XmlDoc.getElementsByTagName('usercontribs')
		var i, len, article
		
		if(XmlContribs.length==0)
		{
			addAlert("impossible de trobar las contribucions de " + User)
			return
		}
		
		XmlContribs = XmlContribs[0].childNodes //per evitar lo query-continue
		
		len = XmlContribs.length
		
		for(i=0;i<len;i++)
		{
			article = XmlContribs[i].attributes.title.value
			if(ACobj.ArticlesWrotten[article]) continue
			if(article.length == 0) continue
			getArticleHistory(article)
		}
		
	}
	
	//avia la requèsta Ajax que cèrca l'istoric
	function getArticleHistory(article)
	{
		ACobj.ArticlesWrotten[article] = true
		
		var req=new XMLHttpRequest()
		req.article = article
		req.onreadystatechange = function()
		{
			if(req.readyState == 4)
			{
				if(req.status==200)
				{
					
					if(!req.responseXML) addAlert("Fracàs al moment de la requèsta de l'istoric de " + req.article)
					else
					{
						var History
						
						cleanQueryContinue(req.responseXML, ACobj.HISTORYLIMIT, req.article)
						
						History = req.responseXML.getElementsByTagName('revisions') 
						if(History.length != 0)
						{
							History = History[0].childNodes
							writeHistory(History, req.article, true)
						}
					}
					
					ACobj.requestStack-- 
					if(ACobj.requestStack==0) setPageLocked(false)
				}
			}
		}
		
		req.open("GET","/w/api.php?action=query&titles=" + article + "&format=xml&prop=revisions&rvlimit=" + AC_historyLimit + "&rvend=" + ACobj.timeStampLimit, true)
		req.setRequestHeader('Content-Type', 'text/xml; charset=utf-8')
		req.send(null)
		
		ACobj.requestStack++
	
	}
	
	//escriu la lista de seguit
	function writeWatchList(XmlDoc)
	{
		var Histories 
		var article, i
		
		Histories = XmlDoc.getElementsByTagName('revisions')
		
		for(i=0;i<Histories.length;i++)
		{
			article = Histories[i].parentNode.attributes.title.value
			writeHistory(Histories[i].childNodes, article, false) //las revisions son marcadas dins lo marrit òrdre :( d'ont youngestFirst
			ACobj.ArticlesWrotten[article] = true
		}
	}
	
	//escriu l'istoric de l'article
	//youngestFirst a true se l'istoric es classat del mai jove al mai vièlh
	function writeHistory(History, article, youngestFirst)
	{
		var table = document.getElementById('tablecontrib')
		var date
		var comment
		var revid
		var user
		var i
			
		if(History.length==1)
		{
			user = History[0].attributes.user.value
			if(History[0].attributes.comment) comment = History[0].attributes.comment.value
			else comment = ""
			revid = History[0].attributes.revid.value
			date = parseDate(History[0].attributes.timestamp.value)
			if(AC_WhiteList.indexOf(user) == -1 || article.indexOf(":") != -1)
				insertLineContrib(table, date, article, comment, revid, user, youngestFirst)
		}
		else
		{
			if(youngestFirst) date = parseDate(History[0].attributes.timestamp.value)
			else date = parseDate(History[History.length-1].attributes.timestamp.value)
			insertMultipleLineContrib(table, date, article, History, youngestFirst)
		}	
	}
	
	//apond una linha html dins lo tablèu a la bona plaça, pels articles o i a una sola contrib
	//NotFollowed se l'article es pas seguit
	function insertLineContrib(table, date, article, comment, revid, User, NotFollowed)
	{
		var row, cell
		var pos 
		var strDate = stringDate(date)
		
		if(!table[strDate])
		{
			table[strDate] = true
			insertDateRow(table, date)
		}
		
		pos = getLineJusteBefore(table, date)
		
		row=table.insertRow(pos)
		row.className='trover'
		if(article == 'Discussion Utilizaire:' + mw.config.get('wgUserName')) row.style.backgroundColor = '#fef3d8'
		row.style.whiteSpace='nowrap'
		row.timeStamp = date.getTime()
			
		insertCellsInMainRow(row, false, article, date, revid, revid, NotFollowed, htmlUserLink(User), comment)
		
	}
	
	
	function insertCellsInMainRow(row, expand, article, date, revid, oldid, NotFollowed, userStr, comment)
	{
		var cell
		
		if(expand) 	insertCellHTML(row, htmlExpandLink(article)) 
		else insertCellText(row, "") 
		
		insertCellText(row, stringHour(date)) 
		insertHistCell(row, article) 
		
		if(expand) insertMultipleDiffCell(row, article, revid, oldid)
		else insertDiffCell(row, article, revid)
		insertEditCell(row,article)
		
		insertCellHTML(row, htmlDeleteLink(article)) 
		insertArticleCell(row, article, !NotFollowed)
		
		cell=insertCellHTML(row, "[" + userStr + "]")
		if(comment.length == 0) cell.colSpan = 2
		else insertCellHTML(row, wikiParse(comment))
		
		insertCellText(row, " ").style.width='100%' 
		
	}
	
	
	
	
	//crea lo sostablèu
	//youngestFirst a true se l'istoric es classat del mai jove al mai vièlh
	function insertMultipleLineContrib(table, date, article, History, youngestFirst)
	{
		var pos
		var strDate = stringDate(date)
		var subtable = document.createElement("table")
		var subcell, subrow, mainrow
		var user
		var userList = new Object()
		var first = true
		var usersStr
		var oldid, revid
		var hide = true 
		
		if(!table[strDate])
		{
			table[strDate] = true
			insertDateRow(table, date)
		}
		
		pos = getLineJusteBefore(table, date)
		
		//la ligne qui contient le tableau
		subrow=table.insertRow(pos)
		subrow.style.whiteSpace='nowrap'
		subrow.timeStamp = date.getTime()
		insertCellHTML(subrow,"")
		subcell=insertCellHTML(subrow, "")
		subcell.colSpan=9
		
		subtable.cellPadding = 0
		subtable.cellSpacing = 0 
		subtable.id = '_ACH_' + article
		subtable.className= 'tablecontrib'
		subtable.style.display='none'
		
		if(youngestFirst)
		{
			revid = History[0].attributes.revid.value
			oldid = History[History.length-1].attributes.revid.value
			
			for(i=0;i!=History.length;i++)
			{
				user = insertLineSubContrib(subtable, article, History[i])
				hide = hide && (AC_WhiteList.indexOf(user) != -1)
				
				if(userList[user]) userList[user]++
				else userList[user] = 1
			}
		}
		else
		{
			revid = History[History.length-1].attributes.revid.value
			oldid = History[0].attributes.revid.value
			
			for(i=History.length-1;i>=0;i--)
			{
				user = insertLineSubContrib(subtable, article, History[i])
				hide = hide && (AC_WhiteList.indexOf(user) != -1)
	
				if(userList[user]) userList[user]++
				else userList[user] = 1
			}
		}
		
		if(!hide || article.indexOf(":") != -1) //se totes los users venon de la whitelist, se l'aficha pas
		{
			//e s'escriu la linha principala, ara que s'a los users
			usersStr = ""
			for(user in userList)
			{
				if(!first) usersStr = usersStr + "; "
				else first = false
				usersStr = usersStr +  htmlUserPageLink(user) 
				if(userList[user] != 1) usersStr = usersStr + " (" +userList[user] + "x)"
			} 
			
			mainrow=table.insertRow(pos)
			mainrow.style.whiteSpace='nowrap'
			mainrow.className='trover'
			if(article == 'Discussion Utilisateur:' + mw.config.get('wgUserName')) mainrow.style.backgroundColor = '#fef3d8'
			mainrow.timeStamp = date.getTime()
			insertCellsInMainRow(mainrow, true, article, date, revid, oldid, youngestFirst, usersStr, "")
			
			subcell.appendChild(subtable)
		}
	}
	
	//linha de contribucion d'un article, retorna l'user
	function insertLineSubContrib(table, article, revision)
	{
		var row =table.insertRow(-1)
		var date = parseDate(revision.attributes.timestamp.value)
		var user = revision.attributes.user.value
		var revid = revision.attributes.revid.value
		var comment = ""
		
		row.className='trover'
		
		if(revision.attributes.comment) comment = revision.attributes.comment.value
	
		insertCellHTML(row, "&nbsp;&nbsp;&nbsp;")
		insertRevisionCell(row, article, date, revid)
		insertDiffCell(row, article, revid)
		insertCellHTML(row, htmlUserLink(user))
		insertCellHTML(row, wikiParse(comment))
		
		return user
	} 
	
	
	//aficha/amaga un istoric
	function expandHistory(article)
	{
		var table = document.getElementById('_ACH_' + article)
		
		if(!table) return
		
		if(table.style.display=='none') table.style.display = ''
		else table.style.display = 'none'
	}
	
	//ligam qu'aficha/amaga la taula de l'istoric d'un article
	function htmlExpandLink(article)
	{
		return '<a title="expand" href="javascript:expandHistory(\'' + article.replace(/'/g, "\\'") + '\')">#</a>'
	
	}
	
	
	//apond una linha amb la data
	function insertDateRow(table, date)
	{
		var localDate = new Date()
		
		localDate.setTime(date.getTime()) 
		localDate.setHours(23, 59, 59, 999)
		
		var pos = getLineJusteBefore(table, localDate)
		var row =table.insertRow(pos)
		var cell = row.insertCell(-1)
		
		row.timeStamp = localDate.getTime()
		
		cell.colSpan=8
		cell.style.paddingTop= '6px'
		cell.style.borderBottom = '1px solid blue'
		cell.innerHTML = "<b>" + stringDate(date) + "</b>"
	}
	
	//cèrca la posicion per l'insercion
	function getLineJusteBefore(table, date)
	{
		var i;
		var timeStamp = date.getTime()
		
		for(i=0; i<table.rows.length;i++)
		{
			if(timeStamp > table.rows[i].timeStamp)
				return i
		}
		
		return i
	}
	
	
	//inserís una cellula formatada amb de l'html dedins
	function insertCellHTML(row, innerHTML)
	{
		var cell=row.insertCell(-1)
		cell.style.paddingRight='3px'
		cell.innerHTML = innerHTML
		cell.style.width='0%'
		
		return cell
	}
	
	//inserís una cellula formatada amb de tèxt dedins
	function insertCellText(row, Text)
	{
		var cell=row.insertCell(-1)
		cell.style.paddingRight='3px'
		cell.textContent = Text
		cell.style.width='0%'
		
		return cell
	}
	
	
	//renvia lo nom del mes
	function getMonthName(m)
	{
		switch(m)
		{
			case 0: {return "genièr"}
			case 1: {return "febrièr"}
			case 2: {return "març"}
			case 3: {return "abril"} 
			case 4: {return "mai"}
			case 5: {return "junh"}
			case 6: {return "julhet"} 
			case 7: {return "agost"}
			case 8: {return "setembre"}
			case 9: {return "octobre"} 
			case 10: {return "novembre"}
			case 11: {return "decembre"}
		}
		
		return ""
	}
	
	//renvia una cadena de caractèrs amb l'ora
	function stringHour(d)
	{
		return toNString(d.getHours(),2) + "h" + toNString(d.getMinutes(), 2) 
	}
	
	//renvia una cadena de caractèrs amb la data
	function stringDate(d)
	{
		return d.getDate() + " " + getMonthName(d.getMonth()) + " " + d.getFullYear() 
	}
	
	
	
	//inserís una cellula formatada amb un anchor hist dedins
	function insertHistCell(row, article) 
	{
		var cell=ACobj.CellWithAnchor.cloneNode(true)
		
		cell.firstChild.title = 'istoric'
		cell.firstChild.href = '/w/index.php?title=' + encodeURIComponent(article) + '&action=history'
		cell.firstChild.textContent = '(hist)'
		
		row.appendChild(cell)
	}
	
	//inserís una cellula formatada amb un anchor cap a una version precisa
	function insertRevisionCell(row, article, date, revid) 
	{
		var cell=ACobj.CellWithAnchor.cloneNode(true)
		
		cell.firstChild.title = 'Version'
		cell.firstChild.href = "/w/index.php?title=" + encodeURIComponent(article) + "&oldid=" + revid
		cell.firstChild.textContent = stringHour(date)
		
		row.appendChild(cell)
	}
	
	//inserís una cellula formatada amb un anchor cap a un diff multiple
	function insertMultipleDiffCell(row, article, revid, oldid) 
	{
		var cell=ACobj.CellWithAnchor.cloneNode(true)
		
		cell.firstChild.title = 'diff'
		cell.firstChild.href = "/w/index.php?title=" + encodeURIComponent(article) + "&diff=" + revid + "&oldid=" + oldid + "&direction=prev"
		cell.firstChild.textContent = "(diff)"
		
		row.appendChild(cell)
	}
	
	//inserís una cellula formatada amb un anchor cap a un diff
	function insertDiffCell(row, article, oldid) 
	{
		var cell=ACobj.CellWithAnchor.cloneNode(true)
		
		cell.firstChild.title = 'diff'
		cell.firstChild.href = "/w/index.php?title=" + encodeURIComponent(article) + "&diff=prev&oldid=" + oldid
		cell.firstChild.textContent = "(diff)"
		
		row.appendChild(cell)
	}
	
	//inserís una cellula formatada amb un ligam edit
	function insertEditCell(row, article) 
	{
		var cell=ACobj.CellWithAnchor.cloneNode(true)
		
		cell.firstChild.title = "editar"
		cell.firstChild.href = "/w/index.php?title=" + encodeURIComponent(article) + "&action=edit"
		cell.firstChild.textContent = "(edit)"
		
		row.appendChild(cell)
	}
	
	
	//inserís una cellula formatada amb un ligam edit
	function insertRevertCell(row, article, token) 
	{
		var cell=ACobj.CellWithAnchor.cloneNode(true)
		
		cell.firstChild.title = "Anullar"
		cell.firstChild.href = "/w/index.php?title=" + encodeURIComponent(article) + "&action=rollback&from=" + encodeURIComponent(mw.config.get('wgUserName')) + "&token=" + token
		cell.firstChild.textContent = "(revert)"
		
		row.appendChild(cell)
	}
	
	
	//inserís una cellula formatada amb un anchor cap a un article
	function insertArticleCell(row, article, redBorder) 
	{
		var cell=ACobj.CellWithAnchor.cloneNode(true)
		
		cell.firstChild.title = article
		cell.firstChild.href = "/wiki/" + article.replace(/ /g,"_");
		if(article.length>90) article = article.substring(0,87) + '...'
		cell.firstChild.textContent = article
		
		if(redBorder) cell.firstChild.style.borderBottom = '1px solid red'
		
		row.appendChild(cell)
	}
	
	//ligam cap a un article
	function htmlArticleLink(article)
	{
		return '<a title="' + article + '" href="/wiki/' + encodeURIComponent(article) + '">' + article + '</a>'
	}
	
	//ligam delete
	function htmlDeleteLink(article)
	{
		if (AC_displayDeleteLink)
			return '<a title="supprimer" href="/w/index.php?title=' + encodeURIComponent(article) + '&action=delete">' + 
			'<img width="14" height="14" style="margin-top:2px" src="//upload.wikimedia.org/wikipedia/commons/thumb/c/ca/Crystal_error.png/14px-Crystal_error.png" longdesc="/wiki/Image:Crystal_error.png"/></a>'
			
		return ""
	}
	
	//ligam user
	function htmlUserLink(User)
	{
		var UserURI = encodeURIComponent(User)
		
		return  htmlUserPageLink(User) + '<small>&nbsp;(' +
				'<a href="/wiki/Discussion_Utilizaire:' + UserURI + '">d</a>&nbsp;' +
				'<a href="/wiki/Special:Contributions/' + UserURI + '">c</a>&nbsp;' +
				'<a href="/wiki/Special:Blockip/' + UserURI + '">b</a>)</small>' 			
	}
	
	//ligam pagina user, soslinha en roge se seguit
	function htmlUserPageLink(User)
	{
		return '<a title="Utilizaire:' + User + '" href="/wiki/Utilizaire:' + encodeURIComponent(User) + '" ' + 
				iif(AC_BlackList.indexOf(User)!=-1, 'style="border-bottom:1px solid red"','') + '>' + User + '</a>'
	
	}