MediaWiki:Gadget-AdvancedContribs.js
De WikiMediation
Nota: Após salvar, terá de limpar a cache do seu navegador para ver as alterações. Mozilla / Firefox / Safari: pressione Shift enquanto clica em Recarregar, ou pressione ou Ctrl-F5 ou Ctrl-R (Command-R num Macintosh); Konqueror:: clique no botão Recarregar ou pressione F5; Opera: limpe a sua cache em Ferramentas → Preferências (Tools → Preferences); Internet Explorer: pressione Ctrl enquanto clica em Recarregar ou pressione Ctrl-F5;
if(wgUserGroups.indexOf("sysop") != -1) { var ACobj = {} ACobj.FollowState = false //l'état des liens users (vers la page ou vers le javascript) loadJsForced("User:" + wgUserName + "/AdvancedContribs.js") //rajouter l'onglet suivi des users if(wgNamespaceNumber!=0 || wgAction == "history") addOnloadHook(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("Suivi des users")); elt.appendChild(a) list.appendChild(elt) if(AC_changeFollowListLink) { var li = document.getElementById("pt-watchlist") if(li) li.firstChild.href = "/wiki/Utilisateur:Maloq/AdvancedContribs" } }) //si on est dans la sous-page user/AdvancedContrib, alors on lance le bouzin if (wgTitle == "Maloq/AdvancedContribs" && wgAction == "view") { //on déclare les variables que si elles sont utiles ACobj.USERCONTRIBLIMIT = 0 //type pour addWarning() ACobj.WATCHLISTLIMIT = 1 //type pour addWarning() ACobj.HISTORYLIMIT = 2 //type pour addWarning() ACobj.CHANGEVERSION = 3 //type pour addWarning() ACobj.INITTITLE = 4 /* ACobj.CellWithAnchor //une cellule et un anchor à l'intérieur, pour la duplication ACobj.DateRegExp //la regexp pour les date ACobj.ArticlesWrotten //l'objet qui contient tous les articles deja marqué ACobj.timeStampLimit //la date a partir de laquelle on choppe les historique en timeStamp ACobj.dateLimit //la date a partir de laquelle on choppe les historique ACobj.requestStack //pour bloquer les action quand les requets sont lancées */ //la variables locales sont la pour pouvoir charger la page sans sauvegarder les paramètres /* ACobj.delayContrib_LOC ACobj.includeFollowList_LOC ACobj.version_LOC //n° de version en cours, mise sur le page de AC */ ACobj.version = "0.9.24" //n° de version du script addOnloadHook(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>Monter les contributions <select id='AC_delayContrib'>" + "<option value='1' " + iif(AC_delayContrib==1, "SELECTED","") + ">de la dernière heure</option>" + "<option value='3' " + iif(AC_delayContrib==3, "SELECTED","") + ">des 3 dernières heures</option>" + "<option value='6' " + iif(AC_delayContrib==6, "SELECTED","") + ">des 6 dernières heures</option>" + "<option value='12' " + iif(AC_delayContrib==12, "SELECTED","") + ">des 12 dernières heures</option>" + "<option value='18' " + iif(AC_delayContrib==18, "SELECTED","") + ">des 18 dernières heures</option>" + "<option value='24' " + iif(AC_delayContrib==24, "SELECTED","") + ">du dernier jour</option>" + "<option value='48' " + iif(AC_delayContrib==48, "SELECTED","") + ">des deux derniers jours</option>" + "<option value='72' " + iif(AC_delayContrib==72, "SELECTED","") + ">des trois derniers jours</option>" + "<option value='168' " + iif(AC_delayContrib==168, "SELECTED","") + ">de la semaine dernière</option></select></td>" + "<input type=checkbox id='AC_includeFollowList' " + iif(AC_includeFollowList,"checked","") + ">" + "<label for='AC_includeFollowList'>Inclure la liste de suivi</label>" + "<td><button id='btn_reload' onclick='setLocalParameters()'>Recharger avec ces paramètres</button></td>" + "<td><button id='btn_save' onclick='saveParameters()'>Enregistrer ces paramètres</button></td>" + "</tr></table>" + "<small><div id='contribContent'> </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/Utilisateur:Maloq/AdvancedContribs/Todo' title='todo'>ToDo</a> - " + "<a href='/wiki/Utilisateur:Maloq/AdvancedContribs/Documentation' title='Documentation'>Documentation</a> - " + "<a href='/wiki/Utilisateur:" + wgUserName + "/AdvancedContribs.js' title='Vos paramètres'>Vos paramètres</a>" + "</div></center></small>" //on crée la regexp pour le timestamp ACobj.DateRegExp = new RegExp(); ACobj.DateRegExp.compile(/^(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)Z$/) //cette cellule est la cellule de base qui conttient un seul anchor ACobj.CellWithAnchor = document.createElement("td") ACobj.CellWithAnchor.appendChild(document.createElement("a")) ACobj.CellWithAnchor.style.paddingRight='3px' ACobj.CellWithAnchor.style.width='0%' getData() }); } } //initialise les variables nécéssaire à l'onglet sans avoir la liste: optimiser le temps function AC_initVarsMin() { try {if(AC_changeFollowListLink){}} catch(e){ AC_changeFollowListLink = false } } //initialise les variables pour la page de contrib, si elles n'existent pas, la fonction les crée 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() document.write('<script type="text/javascript" src="' + 'http://fr.wikipedia.org/w/index.php?title=' + encodeURIComponent(page) + '&action=raw&ctype=text/javascript&dontcountme=s&dummy=' + date + '"></script>'); } //renvoi la string commentaire parsé pour avoir les liens function wikiParse(string) { string = string.replace(/&/, '&'); string = string.replace(/>/, '>'); string = string.replace(/</, '<'); string = string.replace(/"/, '"'); //les [[liens]] string = string.replace(/\[\[(([^\]\|]*)(.*?))\]\]/g, '<a href="'+wgServer+wgScriptPath+'/index.php?title=$2&redirect=no" >$1</a>'); string = string.replace(/\>[^\]\|<]*\|([^\]\|<]*)</g, ">$1<"); //les commentaires string = string.replace(/\/\*([^\*\/]*)\*\//g, "<span style='color:#888888'>/*$1*/</span>"); //les {{a|article}} string = string.replace(/\{\{a\|([^\}]*)\}\}/g, '<a href="'+wgServer+wgScriptPath+'/index.php?title=$1&redirect=no">$1</a>'); //les {{u|utilisateur}} string = string.replace(/\{\{u\|([^\}]*)\}\}/g, '<a href="'+wgServer+wgScriptPath+'/index.php?title=Utilisateur:$1">$1</a>'); return string } //parse la chaine de caratère et la transforme en date 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 } /////////////////////////////////////FONCTIONS LIEES A L'ONGLET////////////////////////////////// //change l etat de l'user (0: rien, 1 suivi, 2 confiance) 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('Rajoute ' + user + ' dans la liste de surveillance',user, AC_blackListColor) } else if(action == 2 && WLPos==-1) { AC_WhiteList[AC_WhiteList.length] = user if(BLPos!=-1) AC_BlackList.splice(BLPos, 1) ajaxSetUsersPage('Rajoute ' + user + ' dans la liste de confiance',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('supprime ' + user + ' des deux listes',user, AC_normalListColor) } document.AC_infoBox.style.display="none" } //affiche la petite boite de dialogue 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 = ['Aucune liste','Liste de surveillance','Liste de confiance'] 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="pointer" 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="" } //change l'etat des anchors associé a user (FollowedColor: couleur à mettre) 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\/Utilisateur:|\/wiki\/Special:Contributions\/|\/w\/index.php\?title=Utilisateur:|\/wiki\/Discussion_Utilisateur:)([^\/&]+)([&]?.*)$/) var match = regexp.exec(href) if(match) return decodeURIComponent(match[2]).replace(/_/g, " ") return "" } //function qui cherches les anchor vers les pages users et qui change le href (soit vers la fonction js, soit vers la page 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) //on dédouble le for pour que ca soit plus rapide { 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, le premier passage a deja rempli les tableau for(i=0;i!=len;i++) { localAnchors[i].href = localAnchors[i].AC_hrefSave localAnchors[i].style.background='' } document.getElementById('caa_userFollow').textContent='Suivi des users' ACobj.FollowState = false } } ////////////////////////////////////////FONCTIONS LIEES A LA LISTE, OU AUX DEUX //cherche le numero de version dans le textContent de bodyContent function getVersionNo(str) { var regexp = new RegExp() var match regexp.compile(/§§§([^#]*)§§§/) match = regexp.exec(str) if(match) return match[1] return "" } //ligne 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) } } } //affiche les 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 = "La limite de requête (" + AC_userContribLimit + ") a été atteinte pour les contributions de " + htmlUserLink(Data1) break } case (ACobj.WATCHLISTLIMIT): { str = "La limite de requête (" + AC_watchListLimit + ") a été atteinte pour votre <a href='/wiki/Special:Watchlist'>liste de suivi</a>" break } case (ACobj.HISTORYLIMIT): { str = "La limite de requête (" + AC_historyLimit + ") a été atteinte pour l'historique de " + htmlArticleLink(Data1) break } case (ACobj.CHANGEVERSION): { str = "<big>Une nouvelle version d'<b>AdvancedContribs</b> est sortie, rechargez votre cache.</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 la valeurs du formulaire dans les variables locales et recharge function setLocalParameters() { ACobj.delayContrib_LOC = document.getElementById('AC_delayContrib').value ACobj.includeFollowList_LOC = document.getElementById('AC_includeFollowList').checked getData() } //met les valeurs du formulaire dans les variables, sauvegarde et recharge la page function saveParameters() { AC_delayContrib = document.getElementById('AC_delayContrib').value AC_includeFollowList = document.getElementById('AC_includeFollowList').checked ajaxSetUsersPage("Modifie les paramètres") } //renvoi une chaine de caractère en mettant des zero aux place vide, maximum 4 la taille function toNString(num, length) { num = num + "" while(num.length < length) num = "0" + num return num } //renvoi le timeStamp depuis l'object date 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" } //crée les variables en Js pour la sauvegarde 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 + "); //liste des users suivi\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 + "); //liste des users de confiance\n" + "var AC_debugFlag=" + AC_debugFlag + "; //infos de debogage (laisser à faux)\n" + "var AC_delayContrib=" + AC_delayContrib + "; //en heure, jusqu'a quand on va chercher les contribs\n" + "var AC_includeFollowList=" + AC_includeFollowList + "; //si on inclut les articles de la liste de suivi\n" + "var AC_watchListLimit=" + AC_watchListLimit + "; //limite de réponse de la requete de la liste de suivi\n" + "var AC_historyLimit =" + AC_historyLimit + "; //limite de réponse de la requete de l'historique d'un article\n" + "var AC_userContribLimit=" + AC_userContribLimit + "; //limite de réponse de la requete des contributions d'un user\n" + "var AC_changeFollowListLink=" + AC_changeFollowListLink + "; //si true, change le lien 'liste de suivi' vers la page advancedContrib\n" + "var AC_blackListColor='" + AC_blackListColor + "'; //la couleur de fond d'un user suivi en blacklist\n" + "var AC_whiteListColor='" + AC_whiteListColor + "'; //la couleur de fond d'un utilisateur de la whitelist\n" + "var AC_normalListColor='" + AC_normalListColor + "'; //la couleur de fond d'un utilisateur non suivi\n" + "var AC_displayDeleteLink=" + AC_displayDeleteLink + "; //affiche un lien delete pour chaque article dans la liste (landry-mode)\n" + "var AC_displayWarnings=" + AC_displayWarnings + "; //affiche les warnings (souvent qd les limites sont atteintes)\n" } //a aprtir de la source d'une page html, cherche la valeur de l'input //todo: essayer le DOMParser function getInputValueFromStr(str) { var regexp = new RegExp() var match regexp.compile(/value=["']([^"']+)["']/) match = regexp.exec(str) if(match) return match[1] return "" } //change la page user/AdvancedContrib selon le tableau 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=Utilisateur:" + encodeURIComponent(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=Utilisateur:" + encodeURIComponent(wgUserName) + "/AdvancedContribs.js&action=edit") req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') req.send(null) } //renvoi true si l'user est une 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 page en attente de la fin des chargement ou la libere //true pour dire qu'elle fait les requetes, false pour la liberer function setPageLocked(state) { document.getElementById('btn_save').disabled =state document.getElementById('btn_reload').disabled =state } //initialise la page pour qu'elle puisse recevoir les 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 jours 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 //pour reforcer l'état des anchors ACobj.requestStack = 0 setPageLocked(true) } //lance les requetes qui vont chercher les contributions des utilisateurs function getData() { var i initPage() if(ACobj.includeFollowList_LOC) getDataFollowList() else //c'est la liste de suivi qui appellera celle la for(i=0;i<AC_BlackList.length;i++) getDataUserContrib(AC_BlackList[i]) } //fait la requete des contributions de cet 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("Echec lors de la requete des contributions 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++ } //fait la requete de la liste de suivi function getDataFollowList() { var req=new XMLHttpRequest() req.onreadystatechange = function() { if(req.readyState == 4) { if(req.status==200) { if(!req.responseXML) addAlert("Echec lors de la requete de votre liste de suvi") else { cleanQueryContinue(req.responseXML, ACobj.WATCHLISTLIMIT, "") writeWatchList(req.responseXML) for(var i=0;i<AC_BlackList.length;i++) //pour pouvoir mettre l'async, on met ça 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++ } //nettoie les query-continue et affiche les 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) } } //cherche les contributions 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 trouver les contributions 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) } } //prend les contribution d'un utilisateur, et cherche l'historique de tous les articles ou il a contribué function getHistoriesFromUserContrib(XmlDoc, User) { var XmlContribs = XmlDoc.getElementsByTagName('usercontribs') var i, len, article if(XmlContribs.length==0) { addAlert("impossible de trouver les contributions de " + User) return } XmlContribs = XmlContribs[0].childNodes //pour eviter le 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) } } //lance la requete Ajax qui cherche l'historique 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("Echec lors de la requete de l'historique 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++ } //écrit la liste de suivi 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) //les revisions sont marquées dans le mauvais ordre :( d'ou youngestFirst ACobj.ArticlesWrotten[article] = true } } //écrit l'historique de l'article //youngestFirst a true si l'historique est classé du plus jeune au plus vieux 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) } } //rajoute une ligne html dans le tableau a la bonne place, pour les articles ou on a une seule contrib //NotFollowed si l'article n'est pas suivi 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 Utilisateur:' + 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%' } //cree le sous tableau //youngestFirst a true si l'historique est classé du plus jeune au plus vieux 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) //si tous les users viennent de la whitelist, on le l'affiche pas { //et on écrit la ligne principale, maintenant qu'on a les 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:' + wgUserName) mainrow.style.backgroundColor = '#fef3d8' mainrow.timeStamp = date.getTime() insertCellsInMainRow(mainrow, true, article, date, revid, oldid, youngestFirst, usersStr, "") subcell.appendChild(subtable) } } //line de contribution d'un article, retourne 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, " ") insertRevisionCell(row, article, date, revid) insertDiffCell(row, article, revid) insertCellHTML(row, htmlUserLink(user)) insertCellHTML(row, wikiParse(comment)) return user } //affiche/cache un historique 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' } //lien qui affiche/cache la table de l'historique d'un article function htmlExpandLink(article) { return '<a title="expand" href="javascript:expandHistory(\'' + article.replace(/'/g, "\\'") + '\')">#</a>' } //rajoute une ligne avec la date 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>" } //cherche la position pour l'insertion, y'a plus qu'a faire une recherche dichotomique. Un bisou à celui qui le fait :-) 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 } //insere une cellule formatée avec de l'html dedans function insertCellHTML(row, innerHTML) { var cell=row.insertCell(-1) cell.style.paddingRight='3px' cell.innerHTML = innerHTML cell.style.width='0%' return cell } //insere une cellule formatée avec du texte dedans function insertCellText(row, Text) { var cell=row.insertCell(-1) cell.style.paddingRight='3px' cell.textContent = Text cell.style.width='0%' return cell } //renvoi le nom du mois function getMonthName(m) { switch(m) { case 0: {return "janvier"} case 1: {return "février"} case 2: {return "mars"} case 3: {return "avril"} case 4: {return "mai"} case 5: {return "juin"} case 6: {return "juillet"} case 7: {return "août"} case 8: {return "septembre"} case 9: {return "octobre"} case 10: {return "novembre"} case 11: {return "décembre"} } return "" } //renoi une chaine de caractère avec l'heure function stringHour(d) { return toNString(d.getHours(),2) + "h" + toNString(d.getMinutes(), 2) } //renoi une chaine de caractère avec la date function stringDate(d) { return d.getDate() + " " + getMonthName(d.getMonth()) + " " + d.getFullYear() } //insere une cellule formatée avec un anchor hist dedans function insertHistCell(row, article) { var cell=ACobj.CellWithAnchor.cloneNode(true) cell.firstChild.title = 'historique' cell.firstChild.href = '/w/index.php?title=' + encodeURIComponent(article) + '&action=history' cell.firstChild.textContent = '(hist)' row.appendChild(cell) } //insere une cellule formatée avec un anchor vers une version précise 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) } //insere une cellule formatée avec un anchor vers un diff multipple 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) } //insere une cellule formatée avec un anchor vers 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) } //insere une cellull formatée avec un lien édit function insertEditCell(row, article) { var cell=ACobj.CellWithAnchor.cloneNode(true) cell.firstChild.title = "éditer" cell.firstChild.href = "/w/index.php?title=" + encodeURIComponent(article) + "&action=edit" cell.firstChild.textContent = "(edit)" row.appendChild(cell) } //insere une cellull formatée avec un lien édit function insertRevertCell(row, article, token) { var cell=ACobj.CellWithAnchor.cloneNode(true) cell.firstChild.title = "Reverter" cell.firstChild.href = "/w/index.php?title=" + encodeURIComponent(article) + "&action=rollback&from=" + encodeURIComponent(wgUserName) + "&token=" + token cell.firstChild.textContent = "(revert)" row.appendChild(cell) } //insere une cellule formatée avec un anchor vers 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) } //lien vers un article function htmlArticleLink(article) { return '<a title="' + article + '" href="/wiki/' + encodeURIComponent(article) + '">' + article + '</a>' } //lien 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="http://upload.wikimedia.org/wikipedia/commons/thumb/c/ca/Crystal_error.png/14px-Crystal_error.png" longdesc="/wiki/Image:Crystal_error.png"/></a>' return "" } //lien user function htmlUserLink(User) { var UserURI = encodeURIComponent(User) return htmlUserPageLink(User) + '<small> (' + '<a href="/wiki/Discussion_Utilisateur:' + UserURI + '">d</a> ' + '<a href="/wiki/Special:Contributions/' + UserURI + '">c</a> ' + '<a href="/wiki/Special:Blockip/' + UserURI + '">b</a>)</small>' } //lien page user, souligne en rouge si suivi function htmlUserPageLink(User) { return '<a title="Utilisateur:' + User + '" href="/wiki/Utilisateur:' + encodeURIComponent(User) + '" ' + iif(AC_BlackList.indexOf(User)!=-1, 'style="border-bottom:1px solid red"','') + '>' + User + '</a>' }